From 835593d77158c1de5070454bbcd79e4879621339 Mon Sep 17 00:00:00 2001 From: "Michael[tm] Smith" Date: Wed, 21 Jun 2017 11:27:19 +0900 Subject: [PATCH] Update expat Fixes https://github.com/w3c/libwww/issues/6 --- Library/src/HTAccess.h | 1048 ++++++-- Library/src/HTAlert.h | 351 ++- Library/src/HTAnchor.h | 929 +++++-- Library/src/HTAtom.h | 121 +- Library/src/HTBTree.h | 134 +- Library/src/HTChunk.h | 295 +- Library/src/HTFTP.h | 125 +- Library/src/HTFile.h | 199 +- Library/src/HTFormat.h | 889 ++++-- Library/src/HTGopher.h | 57 +- Library/src/HTInit.h | 305 ++- Library/src/HTList.h | 209 +- Library/src/HTMIME.h | 166 +- Library/src/HTML.h | 133 +- Library/src/HTMLGen.h | 68 +- Library/src/HTNews.h | 83 +- Library/src/HTParse.h | 267 +- Library/src/HTPlain.h | 49 +- Library/src/HTRules.h | 203 +- Library/src/HTString.h | 153 +- Library/src/HTStyle.h | 202 +- Library/src/HTTCP.h | 176 +- Library/src/HTTP.h | 103 +- Library/src/HTTeXGen.h | 68 +- Library/src/HTTelnet.h | 47 +- Library/src/HTUtils.h | 556 ++-- Library/src/HTWriter.h | 76 +- Library/src/HText.h | 363 ++- Library/src/SGML.h | 275 +- Library/src/windows/wwwinit.def | 28 +- modules/expat/AUTHORS | 10 + modules/expat/CMake.README | 12 +- modules/expat/CMakeLists.txt | 49 +- modules/expat/COPYING | 2 +- modules/expat/Changes | 142 +- modules/expat/MANIFEST | 62 +- modules/expat/Makefile.in | 35 +- modules/expat/README | 2 +- modules/expat/buildconf.sh | 30 + modules/expat/configure.ac | 92 +- modules/expat/conftools/.gitignore | 6 + modules/expat/coverage.sh | 211 ++ modules/expat/doc/.gitignore | 2 + modules/expat/doc/reference.html | 2 +- modules/expat/examples/.gitignore | 8 + modules/expat/examples/elements.c | 6 +- modules/expat/examples/elements.vcxproj | 139 + .../expat/examples/elements.vcxproj.filters | 22 + modules/expat/examples/outline.c | 4 - modules/expat/examples/outline.vcxproj | 150 ++ .../expat/examples/outline.vcxproj.filters | 22 + modules/expat/expat.sln | 73 + modules/expat/expat.spec | 113 + modules/expat/gennmtab/.gitignore | 3 + modules/expat/gennmtab/gennmtab.c | 429 +++ modules/expat/lib/.gitignore | 18 + modules/expat/lib/expat.h | 22 +- modules/expat/lib/expat.vcxproj | 177 ++ modules/expat/lib/expat.vcxproj.filters | 80 + modules/expat/lib/expat_external.h | 5 +- modules/expat/lib/expat_static.vcxproj | 147 + .../expat/lib/expat_static.vcxproj.filters | 71 + modules/expat/lib/expatw.vcxproj | 177 ++ modules/expat/lib/expatw.vcxproj.filters | 80 + modules/expat/lib/expatw_static.vcxproj | 147 + .../expat/lib/expatw_static.vcxproj.filters | 71 + modules/expat/lib/siphash.h | 355 +++ modules/expat/lib/winconfig.h | 10 + modules/expat/lib/xmlparse.c | 609 ++++- modules/expat/lib/xmlrole.c | 10 +- modules/expat/lib/xmltok.c | 34 +- modules/expat/make-release.sh | 75 + modules/expat/memory-sanitizer-blacklist.txt | 6 + modules/expat/qa.sh | 130 + modules/expat/run.sh.in | 12 + modules/expat/tests/.gitignore | 9 + modules/expat/tests/benchmark/benchmark.c | 4 - modules/expat/tests/benchmark/benchmark.sln | 25 + .../expat/tests/benchmark/benchmark.vcxproj | 143 + modules/expat/tests/memcheck.c | 173 ++ modules/expat/tests/memcheck.h | 34 + modules/expat/tests/minicheck.c | 5 +- modules/expat/tests/minicheck.h | 3 +- modules/expat/tests/runtests.c | 2393 +++++++++++++++-- modules/expat/tests/runtests.sln | 24 + modules/expat/tests/runtests.vcxproj | 140 + modules/expat/tests/runtests.vcxproj.filters | 42 + modules/expat/tests/xmltest.log.expected | 35 + modules/expat/tests/xmltest.sh | 5 +- modules/expat/win32/.gitignore | 10 + modules/expat/win32/MANIFEST.txt | 2 - modules/expat/win32/README.txt | 21 +- modules/expat/win32/expat.iss | 24 +- modules/expat/xmlwf/.gitignore | 6 + modules/expat/xmlwf/codepage.c | 6 +- modules/expat/xmlwf/filemap.h | 12 + modules/expat/xmlwf/readfilemap.c | 17 +- modules/expat/xmlwf/unixfilemap.c | 4 + modules/expat/xmlwf/win32filemap.c | 7 +- modules/expat/xmlwf/xmlfile.c | 51 +- modules/expat/xmlwf/xmlwf.c | 8 +- modules/expat/xmlwf/xmlwf.vcxproj | 163 ++ modules/expat/xmlwf/xmlwf.vcxproj.filters | 48 + 103 files changed, 12315 insertions(+), 2639 deletions(-) create mode 100644 modules/expat/AUTHORS create mode 100755 modules/expat/buildconf.sh create mode 100644 modules/expat/conftools/.gitignore create mode 100755 modules/expat/coverage.sh create mode 100644 modules/expat/doc/.gitignore create mode 100644 modules/expat/examples/.gitignore create mode 100644 modules/expat/examples/elements.vcxproj create mode 100644 modules/expat/examples/elements.vcxproj.filters create mode 100644 modules/expat/examples/outline.vcxproj create mode 100644 modules/expat/examples/outline.vcxproj.filters create mode 100644 modules/expat/expat.sln create mode 100644 modules/expat/expat.spec create mode 100755 modules/expat/gennmtab/.gitignore create mode 100644 modules/expat/gennmtab/gennmtab.c create mode 100644 modules/expat/lib/.gitignore create mode 100644 modules/expat/lib/expat.vcxproj create mode 100644 modules/expat/lib/expat.vcxproj.filters create mode 100644 modules/expat/lib/expat_static.vcxproj create mode 100644 modules/expat/lib/expat_static.vcxproj.filters create mode 100644 modules/expat/lib/expatw.vcxproj create mode 100644 modules/expat/lib/expatw.vcxproj.filters create mode 100644 modules/expat/lib/expatw_static.vcxproj create mode 100644 modules/expat/lib/expatw_static.vcxproj.filters create mode 100644 modules/expat/lib/siphash.h create mode 100755 modules/expat/make-release.sh create mode 100644 modules/expat/memory-sanitizer-blacklist.txt create mode 100755 modules/expat/qa.sh create mode 100644 modules/expat/run.sh.in create mode 100644 modules/expat/tests/.gitignore create mode 100644 modules/expat/tests/benchmark/benchmark.sln create mode 100644 modules/expat/tests/benchmark/benchmark.vcxproj create mode 100644 modules/expat/tests/memcheck.c create mode 100644 modules/expat/tests/memcheck.h create mode 100644 modules/expat/tests/runtests.sln create mode 100644 modules/expat/tests/runtests.vcxproj create mode 100644 modules/expat/tests/runtests.vcxproj.filters create mode 100644 modules/expat/tests/xmltest.log.expected create mode 100644 modules/expat/win32/.gitignore create mode 100755 modules/expat/xmlwf/.gitignore create mode 100644 modules/expat/xmlwf/xmlwf.vcxproj create mode 100644 modules/expat/xmlwf/xmlwf.vcxproj.filters diff --git a/Library/src/HTAccess.h b/Library/src/HTAccess.h index fac81181..7bd813b4 100644 --- a/Library/src/HTAccess.h +++ b/Library/src/HTAccess.h @@ -1,236 +1,944 @@ -/* */ +/* + + + W3C Sample Code Library libwww Accessing URIs + -/* Access Manager HTAccess.h -** ============== -** -** This module keeps a list of valid protocol (naming scheme) specifiers -** with associated access code. It allows documents to be loaded given -** various combinations of parameters. -** -** New access protocols may be registered at any time. -** +! + Accessing URIs +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module is the application interface module to the +Request class. It contains a lot of methods for +loading URIs and also for uploading URIs using PUT or +POST, for example. You can use the Request class directly but +this module makes it easier to use by providing a lot of small request functions +using the Request class in different ways. It contains help functions for +accessing documents and for uploading documents to a remote server. + +This module contains functions for handling all HTTP/1.1 methods: + + + GET Requests + + + o + Various GET requests including specialized functions like + loading a rule file, etc. + o + Search requests based on the GET method + o + Formdata requests based on the GET method + + + PUT Requests + + + o + Save a document from memory ASIS using PUT + o + Save a structured document from memory using PUT + o + Save any URI (FTP, HTTP, local disk) using PUT + + + POST Requests + + + o + Post Formdata to a remote HTTP server + o + Post a document from memory ASIS to a remote HTTP + server + + + HEAD, DELETE, OPTIONS, and TRACE requests + + + o + Get metainformation about a document using HEAD requests + o + Delete documents based on the DELETE method + o + Get information about the features supoprted by a resource + using OPTIONS + o + Trace a request using the TRACE method + + + +Furthermore, it contains a few access methods for handling +incoming requests - in orther words acting as a server. Although libwww +is primarily for clients, it is in fact symmetric in that it can handle both +client requests and server requests. + +This module is implemented by HTAccess.c, and it +is a part of the W3C Sample Code +Library. */ #ifndef HTACCESS_H #define HTACCESS_H -/* Definition uses: -*/ -#include "HTUtils.h" -#include "tcp.h" +#include "HTReq.h" #include "HTAnchor.h" -#include "HTFormat.h" -#ifdef SHORT_NAMES -#define HTClientHost HTClHost -#endif +#ifdef __cplusplus +extern "C" { +#endif + -/* Return codes from load routines: -** -** These codes may be returned by the protocol modules, -** and by the HTLoad routines. -** In general, positive codes are OK and negative ones are bad. +/* +. + Load a Document (Method = GET) +. + +URIs can be accesses using a character string, for example +"http://www.w3.org" or it can be accessed by using the libwww +representation of a URI called an Anchor object. +Note that we call all objects accessible through URIs for documents +- this is a notion we have inherited from the hypertext world. +( + Load a Document from Absolute URI +) + +Request a document referencd by an absolute URI. The output from the +request is passed to the Stream Pipe Manager +that figures out where to pump the data. This can for example be to the display +or to a local file depending on the set of +converters registered by the application. */ +extern BOOL HTLoadAbsolute (const char * url, HTRequest * request); -#define HT_NO_DATA -9999 /* return code: OK but no data was loaded */ - /* Typically, other app started or forked */ +/* +( + Load a Document from Relative URI +) -/* Default Addresses */ -/* ================= */ +Request a document referenced by a relative URI. The relative URI +is made absolute by resolving it relative to the address of the 'base' +anchor. +*/ +extern BOOL HTLoadRelative (const char * relative, + HTParentAnchor * base, + HTRequest * request); -#define LOGICAL_DEFAULT "WWW_HOME" /* Defined to be the home page */ +/* +( + Load a Document into Memory +) + +Request a document referred to by the URI and load it into a +HTChunk object. A chunk +object is a dynamic string so in the end you will have a single memory +buffer containing the document. The chunk must be freed by the caller. +*/ +extern HTChunk * HTLoadToChunk (const char * url, HTRequest * request); +/* +( + Load a Document and Save as a Local File +) + +This function loads a URI and saves the contents in the specifed file. The +file should not  be open, as the load function both opens and closes +the file. If the file already exists then it asks the user whether the file +should be overwritten or not. the contents is saved ASIS - that is +- we do not touch the contents of the file! +*/ -#ifndef LOCAL_DEFAULT -#define LOCAL_DEFAULT "file:/usr/local/lib/WWW/default.html" -#define LOCAL_DEFAULT_FILE "/usr/local/lib/WWW/default.html" -#define REMOTE_ADDRESS "http://info.cern.ch/remote.html" /* can't be file */ -#endif +extern BOOL HTLoadToFile (const char * url, HTRequest * request, + const char * filename); -/* If run from telnet daemon and no -l specified, use this file: +/* +( + Load a Document and put the Contents into a Stream +) + +Request a document referenced by an absolute URI and sending the data down +a stream. This stream can be anny stream you like, for eample one from the +Stream Interface. */ -#ifndef DEFAULT_LOGFILE -#define DEFAULT_LOGFILE "/usr/adm/www-log/www-log" -#endif -/* If the home page isn't found, use this file: +extern BOOL HTLoadToStream (const char * url, HTStream * output, + HTRequest * request); + +/* +( + Load a Document using an Anchor +) + +Here the URI is represented by an Anchor object. +You can get an anchor object representing a URI by passing the URI to the +appropriate method in the Anchor class. */ -#ifndef LAST_RESORT -#define LAST_RESORT "http://info.cern.ch:80/default.html" -#endif +extern BOOL HTLoadAnchor (HTAnchor * anchor, HTRequest * request); +/* +( + Load a Document into Memory using an Anchor +) + +This is the same as HTLoadToChunk but instead of passing a URI +string you pass an HTAnchor object. Internally, +all URIs are represented as anchors which contains all the information we +have about the resource. The chunk must be freed by the caller. +*/ +extern HTChunk * HTLoadAnchorToChunk (HTAnchor * anchor, HTRequest * request); -/* Flags which may be set to control this module +/* +( + Recursively Request a Document using Anchors +) + +Same as HTLoadAnchor() but the information in the +error stack in the request +object is kept, so that any error messages in one. This function is almost +identical to HTLoadAnchor, but it doesn't clear the error stack +so that the information in there is kept. */ -extern int HTDiag; /* Flag: load source as plain text */ -extern char * HTClientHost; /* Name or number of telnetting host */ -extern FILE * logfile; /* File to output one-liners to */ -extern HTStream* HTOutputStream; /* For non-interactive, set this */ -extern HTFormat HTOutputFormat; /* To convert on load, set this */ +extern BOOL HTLoadAnchorRecursive (HTAnchor * anchor, HTRequest * request); +/* +. + Load Special Documents +. + +We also have a set of functions for loading special files like rules files +which also are referenced by a URI but which do have to be treated specially. +( + Load a Rule File +) + +Rule files can be loaded just like any other URI but you can also just use +these functions which do all the work for you: they load a rule find with +the URI specified and add the set of rules to the existing set. + +They come in two flavours - one that asks the user whether it is OK to add +the rules and one that does it automatically without asking. As the app would +have to call this method explicitly, it may have other ways of protecting +the user. + +Both functions use preemptive requests +so that everything else stops in the meantime. +*/ + +extern BOOL HTLoadRules (const char * url); +extern BOOL HTLoadRulesAutomatically (const char * url); -/* Load a document -** --------------- -** -** On Entry, -** anchor is the node_anchor for the document -** full_address The address of the document to be accessed. -** filter if YES, treat stdin as HTML -** -** On Exit, -** returns YES Success in opening document -** NO Failure -** +/* +. + Search a Document (Method = GET) +. + +The search methods all use GET as the method in the +HTTP request. The functions take +the keywords and encode them according to +RFC +1866 (Hypertext Markup language). That is, the query part is separated +from the rest of the URI by a "?". + +The keywords are passed to the function as a Chunk +Object and each keyword must be separated by a space ' '. This +will then be converted into a '+' before added to the URI. +( + Search a Document from Absolute URI +) */ -#ifdef NOT_USED -extern BOOL HTLoadDocument PARAMS((HTParentAnchor * anchor, - CONST char * full_address, - BOOL filter, - HTStream* sink)); -#endif +extern BOOL HTSearchAbsolute (HTChunk * keywords, + const char * base, + HTRequest * request); + +/* +( + Search a Document from Relative URI +) + +Search a document referenced by a relative URI. The relative URI is +made absolute by resolving it relative to the address of the 'base' +anchor. +*/ + +extern BOOL HTSearchRelative (HTChunk * keywords, + const char * relative, + HTParentAnchor * base, + HTRequest * request); + +/* +( + Search a Document using an Anchor +) +*/ + +extern BOOL HTSearchAnchor (HTChunk * keywords, + HTAnchor * anchor, + HTRequest * request); + +/* +( + Search a Document using an Anchor Using a String +) + +This works exactly as the HTSearchAnchor() function but takes +a C string instead of a chunk object. +*/ + +extern BOOL HTSearchString (const char * keywords, + HTAnchor * anchor, + HTRequest * request); + +/* +. + Submit Forms Using GET Method +. + +Formdata can be sent to an HTTP server in two ways - it can either use a +GET method or it can use a POST method. The difference +is whether the request "has side effects" or not. For example, if you are +ordering a pizza then the (hopefully positive) sideeffect is that you actually +get one delivered. However, if you are issuing search data - for example +to Alta Vista, then there is no sideeffect. In the former example you would +use the GET form and in the latter you would use the +POST form. +( + Submit Form from Absolute URI using GET +) + +Submit formdata using GET to the address indicated as the "base" which must +be an absolute URI. The list of form data must be given as an +association list where the name is the field name +and the value is the value of the field. +*/ + +extern BOOL HTGetFormAbsolute (HTAssocList * formdata, + const char * base, + HTRequest * request); + +/* +( + Submit Form from Relative URI using GET +) + +Submit formdata using GET to the address indicated relative to the address +of the base anchor. The list of form data must be given as an +association list where the name is the field name +and the value is the value of the field. +*/ + +extern BOOL HTGetFormRelative (HTAssocList * formdata, + const char * relative, + HTParentAnchor * base, + HTRequest * request); + +/* +( + Send a Form using an Anchor and the GET Method +) + +Submit formdata using GET to the address indicated of the anchor. The list +of form data must be given as an association list +where the name is the field name and the value is the value of the field. +*/ + +extern BOOL HTGetFormAnchor (HTAssocList * formdata, + HTAnchor * anchor, + HTRequest * request); + +/* +. + Submit Forms Using POST Method +. + +The data in a POST form is sent as the body part of the +HTTP message whereas a +GET form wraps it all up into the URI. In order to be able to +use the POST data object at a later point in time, we create +a new anchor on the fly. This anchor has a URI file location which points +into the temporary area given by the User Profile +Object. That is - you can actually save the anchor using a +PUT request and then be able to retrive the form data at a later +point in time. Even though this may seem "ambitious" for posting form data, +it is really just a special example of sending any kind of data to a remote +server. All POST form functions return the new anchor or +NULL if they fail. +( + Submit Form from Absolute URI using POST +) + +Submit formdata using POST to the address indicated as the "base" which must +be an absolute URI. The list of form data must be given as an +association list where the name is the field name +and the value is the value of the field. +*/ + +extern HTParentAnchor * HTPostFormAbsolute (HTAssocList * formdata, + const char * base, + HTRequest * request); + +/* +( + Submit Form from a Relative URI using GET +) + +Submit formdata using POST to the address indicated relative to the address +of the base anchor. The list of form data must be given as an association +list where the name is the field name and the value is the value of the field. +*/ + +extern HTParentAnchor * HTPostFormRelative (HTAssocList * formdata, + const char * relative, + HTParentAnchor * base, + HTRequest * request); + +/* +( + Submit Form using an Anchor and the POST Method +) + +Submit formdata using POST to the address indicated of the anchor. The list +of form data must be given as an association list +where the name is the field name and the value is the value of the field. +*/ + +extern HTParentAnchor * HTPostFormAnchor (HTAssocList * formdata, + HTAnchor * anchor, + HTRequest * request); + +/* +( + Submit Form and Save the Result in a Memory Buffer +) + +Submit formdata to the address referred to by the +HTAnchor object and load the result of the POST +into a HTChunk object. A +chunk object is a dynamic memory buffer so in +the end you will have a single memory buffer containing the document. The +chunk must be freed by the caller. +*/ + +extern HTChunk * HTPostFormAnchorToChunk (HTAssocList * formdata, + HTAnchor * anchor, + HTRequest * request); + +/* +. + Get Metainformation about a Document (Method = HEAD) +. + +If you are not interested in the document itself but only in the +metainformation that describes the document then you should +use the HEAD method in your request. +( + Get Metainformation about a Document from Absolute URI +) + +Request metainfomration about a document referencd by an absolute +URI. +*/ +extern BOOL HTHeadAbsolute (const char * url, HTRequest * request); +/* +( + Get Metainformation about a Document from Relative URI +) + +Request metainformation about a document referenced by a relative +URI. +*/ +extern BOOL HTHeadRelative (const char * relative, + HTParentAnchor * base, + HTRequest * request); + +/* +( + Get Metainformation about a Document using an Anchor +) + +Here the URI is represented by an Anchor object. +You can get an anchor object representing a URI by passing the URI to the +approproiate method in the Anchor class. +*/ +extern BOOL HTHeadAnchor (HTAnchor * anchor, HTRequest * request); + +/* +. + Delete a Document (Method = DELETE) +. + +If you want to delete a document (or make the document inaccessible for future +references) then you can use the DELETE method in your request. +( + Delete a Document from Absolute URI +) + +Request metainfomration about a document referencd by an absolute +URI. +*/ +extern BOOL HTDeleteAbsolute (const char * url, HTRequest * request); + +/* +( + Delete a Document from Relative URI +) + +Request metainformation about a document referenced by a relative +URI. +*/ +extern BOOL HTDeleteRelative (const char * relative, + HTParentAnchor * base, + HTRequest * request); + +/* +( + Delete a Document using an Anchor +) + +Here the URI is represented by an Anchor object. +You can get an anchor object representing a URI by passing the URI to the +approproiate method in the Anchor class. +*/ +extern BOOL HTDeleteAnchor (HTAnchor * anchor, HTRequest * request); + +/* +. + Save a Document ASIS From Memory (Method = PUT) +. + +If you already have a document in memory and it is associated with an +Anchor object then you can PUT this document +to a remote server using the following methods. Other information that you +can set in the anchor is metadata like the media type, the document length, +the language, or any other information that you want to associate with the +document to be uploaded. + +This set of functions takes the document ASIS - that it the +exact content of the document associated with this anchor will be +sent to the remote server. If your anchor represents a structured content +and the document itself is a parse tree, for example, then you can use the +structured PUT functions. + +If your application is an editor, then you may want to create a new anchor +on the fly for temporary backups on local disk before you save it to a remote +server. An easy way to get a new anchor with a local file URI is to use the +HTTmpAnchor function which is part of the +WWWApp interface. +( + Save a Document ASIS from Memory Using Absolute URI (PUT) +) + +The source is an anchor with the contents already in memory and the destination +is an absolute URI. +*/ + +extern BOOL HTPutAbsolute (HTParentAnchor * source, + const char * destination, + HTRequest * request); + +/* +( + Save a Document ASIS from Memory Using Relative URI (PUT) +) + +The source is an anchor with the contents already in memory and the destination +is a relative URI relative to the destination anchor +*/ + +extern BOOL HTPutRelative (HTParentAnchor * source, + const char * relative, + HTParentAnchor * destination_base, + HTRequest * request); + +/* +( + Save a Document ASIS from Memory Using an Anchor (PUT) +) + +Both the source and the anchor are anchor objects. The source anchor already +has the contents in memory +*/ + +extern BOOL HTPutAnchor (HTParentAnchor * source, + HTAnchor * dest, + HTRequest * request); + +/* +. + Save a Structured Document (Using PUT) +. + +If you want to save a document from memory but it contains structured information +(for example, it is in the form of a parse tree) then you can use this interface. +The only difference from above is that the caller must provide the function +that provides data while sending it accross the network - we can't just take +it as a block. You can for example have a look at the +HTEntity_callback function which is used in the +ASIS interface if you want to write your own +data feeding method. +( + Save a Structured Document from Memory to Absolute URI (PUT) +) + +Upload a document referenced by an absolute URI. +*/ + +extern BOOL HTPutStructuredAbsolute (HTParentAnchor * source, + const char * destination, + HTRequest * request, + HTPostCallback * input); + +/* +( + Save a Structured Document from Memory to Relative URI (PUT) +) + +The source is an anchor with the contents already in memory and the destination +is a relative URI relative to the destination anchor +*/ + +extern BOOL HTPutStructuredRelative (HTParentAnchor * source, + const char * relative, + HTParentAnchor * destination_base, + HTRequest * request, + HTPostCallback * input); + +/* +( + Save a Structured Document Using an Anchor and the PUT Method +) + +The source is an anchor with the contents already in memory and the destination +is a relative URI. The HTPostCallback function type is declared in the HTRequest +object. +*/ -/* Load a document from relative name -** --------------- -** -** On Entry, -** relative_name The relative address of the file to be accessed. -** here The anchor of the object being searched -** -** On Exit, -** returns YES Success in opening file -** NO Failure -** -** +extern BOOL HTPutStructuredAnchor (HTParentAnchor * source, + HTAnchor * destination, + HTRequest * request, + HTPostCallback * input); + +/* +. + Save a Remote Document (Using PUT) +. + +If the content of the document associated with the anchor is NOT in +memory then you can use this interface. These methods make two requests: +first they go out and get the source which can be on an FTP server, on local +disk, on another HTTP server etc. and then they PUT this document ASIS to +the destination HTTP server. +( + Save a Document from Absolute URI using PUT +) + +Get the source and PUT it to the destination which is an absolute URI */ -extern BOOL HTLoadRelative PARAMS(( - CONST char * relative_name, - HTParentAnchor * here)); +extern BOOL HTPutDocumentAbsolute (HTParentAnchor * source, + const char * destination, + HTRequest * request); +/* +( + Save a Document from Relative URI using PUT +) -/* Load a document from absolute name -** --------------- -** -** On Entry, -** addr The absolute address of the document to be accessed. -** filter if YES, treat document as HTML -** -** On Exit, -** returns YES Success in opening document -** NO Failure -** -** Note: This is equivalent to HTLoadDocument +Get the source and PUT it to the destination which is a relative URI */ -extern BOOL HTLoadAbsolute PARAMS((CONST char * addr)); +extern BOOL HTPutDocumentRelative (HTParentAnchor * source, + const char * relative, + HTParentAnchor * destination_base, + HTRequest * request); +/* +( + Save a Document Using an Anchor and the PUT Method +) -/* Load a document from absolute name to a stream -** --------------- -** -** On Entry, -** addr The absolute address of the document to be accessed. -** filter if YES, treat document as HTML -** -** On Exit, -** returns YES Success in opening document -** NO Failure -** -** Note: This is equivalent to HTLoadDocument +Get the source and PUT it to the destination which is an anchor object. */ -extern BOOL HTLoadToStream PARAMS((CONST char * addr, BOOL filter, - HTStream * sink)); +extern BOOL HTPutDocumentAnchor (HTParentAnchor * source, + HTAnchor * destination, + HTRequest * request); +/* +. + Post a Document from Memory ASIS (Method = POST) +. + +If you already have a document in memory and it is associated with an +Anchor object then you can POST this document +to a remote server using the following methods. Other information that you +can set in the anchor is metadata like the media type, the document length, +the language, or any other information that you want to associate with the +document to be uploaded. + +This set of functions takes the document ASIS - that it the +exact content of the document associated with this anchor will be +sent to the remote server. + +If your application is an editor, then you may want to create a new anchor +on the fly for temporary backups on local disk before you save it to a remote +server. An easy way to get a new anchor with a local file URI is to use the +HTTmpAnchor function which is part of the +WWWApp interface. +( + Post a Document from Memory ASIS using Absolute URI (POST) +) + +Upload a document using POST referenced by an absolute URI. +*/ -/* Load if necessary, and select an anchor -** -------------------------------------- -** -** On Entry, -** destination The child or parenet anchor to be loaded. -** -** On Exit, -** returns YES Success -** NO Failure -** +extern BOOL HTPostAbsolute (HTParentAnchor * source, + const char * destination, + HTRequest * request); + +/* +( + Post a Document from Memory ASIS using Relative URI (POST) +) + +Upload a document using POST referenced by a relative URI. +*/ + +extern BOOL HTPostRelative (HTParentAnchor * source, + const char * relative, + HTParentAnchor * destination_base, + HTRequest * request); + +/* +( + Post a Document from Memory ASIS using an Anchor (POST) +) + +POST an anchor - here both the source and the anchor are anchor objects. +The source anchor already has the contents in memory. */ -extern BOOL HTLoadAnchor PARAMS((HTAnchor * destination)); +extern BOOL HTPostAnchor (HTParentAnchor * source, + HTAnchor * dest, + HTRequest * request); +/* +. + Get Available Options for a Document (Method = OPTIONS) +. + +If you want to get information about a document then you can use the the +OPTIONS method in your request. The OPTIONS method +represents a request for information about the communication options available +on the request/response chain identified by the Request-URI. +This method allows the client to determine the options and/or requirements +associated with a resource, or the capabilities of a server, without implying +a resource action or initiating a resource retrieval. + +A speciality about the OPTIONS method is that the client can +issue a request with no pathinfo at all but only with a "*". +That is, the request line can look like this "OPTIONS * HTTP/1.1". +This means that we request information about the server as a whole and not +only about a single URI. You can get this effect by using a URI containing +the hostname alone with NO extra slash at the end, for example +http://www.w3.org, http://www.cern.ch. +( + Options Available for Document from Absolute URI +) + +Request options about a document referencd by an absolute URI. +*/ +extern BOOL HTOptionsAbsolute (const char * url, HTRequest * request); + +/* +( + Options Available for Document from Relative URI +) -/* Make a stream for Saving object back -** ------------------------------------ -** -** On Entry, -** anchor is valid anchor which has previously beeing loaded -** On exit, -** returnes 0 if error else a stream to save the object to. -** +Request options about a document referenced by a relative URI. */ -extern HTStream * HTSaveStream PARAMS((HTParentAnchor * anchor)); +extern BOOL HTOptionsRelative (const char * relative, + HTParentAnchor * base, + HTRequest * request); +/* +( + Options Available for Document using an Anchor +) -/* Search -** ------ -** Performs a search on word given by the user. Adds the search words to -** the end of the current address and attempts to open the new address. -** -** On Entry, -** *keywords space-separated keyword list or similar search list -** here The anchor of the object being searched +Here the URI is represented by an Anchor object. +You can get an anchor object representing a URI by passing the URI to the +appropriate method in the Anchor class. */ +extern BOOL HTOptionsAnchor (HTAnchor * anchor, HTRequest * request); -extern BOOL HTSearch PARAMS((CONST char * keywords, HTParentAnchor* here)); +/* +. + Get Trace Loop back Information for a Document (Method = + TRACE) +. + +The TRACE method is used to invoke a remote, application-layer loop-back +of the request message. The final recipient of the request SHOULD reflect +the message received back to the client as the entity-body of a 200 (OK) +response. The final recipient is either the origin server or the first proxy +or gateway to receive a Max-Forwards value of zero (0) in the request (see +section 14.31). A TRACE request MUST NOT include an entity. + +TRACE allows the client to see what is being received at the other end of +the request chain and use that data for testing or diagnostic information. +The value of the Via header field (section 14.44) is of particular interest, +since it acts as a trace of the request chain. Use of the Max-Forwards header +field allows the client to limit the length of the request chain, which is +useful for testing a chain of proxies forwarding messages in an infinite +loop. + +If successful, the response SHOULD contain the entire request message in +the entity-body, with a Content-Type of "message/http". Responses +to this method MUST NOT be cached. +( + Traces Available for Document from Absolute URI +) + +Request traces about a document referencd by an absolute URI. +*/ +extern BOOL HTTraceAbsolute (const char * url, HTRequest * request); +/* +( + Traces Available for Document from Relative URI +) -/* Search Given Indexname -** ------ -** Performs a keyword search on word given by the user. Adds the keyword to -** the end of the current address and attempts to open the new address. -** -** On Entry, -** *keywords space-separated keyword list or similar search list -** *addres is name of object search is to be done on. +Request traces about a document referenced by a relative URI. */ +extern BOOL HTTraceRelative (const char * relative, + HTParentAnchor * base, + HTRequest * request); -extern BOOL HTSearchAbsolute PARAMS(( - CONST char * keywords, - CONST char * indexname)); +/* +( + Traces Available for Document using an Anchor +) +Here the URI is represented by an Anchor object. +You can get an anchor object representing a URI by passing the URI to the +appropriate method in the Anchor class. +*/ +extern BOOL HTTraceAnchor (HTAnchor * anchor, HTRequest * request); -/* Register an access method -** ------------------------- +/* +. + Serve a Request +. + +Although libwww is primarily for clients, it is in fact symmetric in that +it can handle both client requests and server requests. The way this is handled +is that each protocol is registered with both a +client handler and a server handler - depending on which type of request +you use, one of them is called. Note that in order to be able to serve any +document, there actually have to be a server handler. However, libwww only +comes with a raw socket loader which isn't much +of a server. There is an attempt of an HTTP server +but it is not complete + +The protocol handler used to serve the request is determined by the URI - +just as for client side requests. That is, libwww can in fact simultaneously +be the server for multiple protocols if you really want to. Examples of URIs +that you can use are noop://localhost:8888 which means that libwww +starts listening on port 8888 (see the listen +example for details). Other examples are http://localhost:7777 +which means that it listens for HTTP on port 7777. Again, there is no HTTP +server in libwww - this is just an example. */ -typedef struct _HTProtocol { - char * name; - - int (*load)PARAMS(( - CONST char * full_address, - HTParentAnchor * anchor, - HTFormat format_out, - HTStream* sink)); - - HTStream* (*saveStream)PARAMS((HTParentAnchor * anchor)); +extern BOOL HTServeAbsolute (const char * address, HTRequest * request); -} HTProtocol; +/* +. + Save a URI To Multiple Destinations - Not supported!!! +. + +Note: This is no longer supported + +These are the generic versions of the PUT and POST +functions. They can be used to send documents to multiple destinations +simultanously using the PostWeb model. +( + Copy an anchor - not supported +) + +Fetch the URI from either local file store or from a remote HTTP server +and send it using either PUT or POST to the remote destination using HTTP. +The caller can decide the exact method used and which HTTP header fields +to transmit by setting the user fields in the request structure. If posting +to NNTP then we can't dispatch at this level but must pass the source anchor +to the news module that then takes all the refs to NNTP and puts into the +"newsgroups" header Returns YES if request accepted, else NO +*/ +extern BOOL HTCopyAnchor (HTAnchor * src_anchor, HTRequest * main_req); -extern BOOL HTRegisterProtocol PARAMS((HTProtocol * protocol)); +/* +( + Upload an Anchor - not supported +) + +This function can be used to send data along with a request to a remote server. +It can for example be used to POST form data to a remote HTTP server - or +it can be used to post a newsletter to a NNTP server. In either case, you +pass a callback function which the request calls when the remote destination +is ready to accept data. In this callback you get the current request object +and a stream into where you can write data. It is very important that you +return the value returned by this stream to the Library so that it knows +what to do next. The reason is that the outgoing stream might block or an +error may occur and in that case the Library must know about it. If you do +not want to handle the stream interface yourself then you can use the +HTUpload_callback which is declared below. The source anchor +represents the data object in memory and it points to the destination anchor +by using the POSTWeb method. +The source anchor contains metainformation about the data object in memory +and the destination anchor represents the reponse from the remote server. +Returns YES if request accepted, else NO +*/ +extern BOOL HTUploadAnchor (HTAnchor * source_anchor, + HTRequest * request, + HTPostCallback * callback); +/* +( + POST Callback Handler - not supported +) + +Is you do not want to handle the stream interface on your own, you can use +this "middleman" function which does the actual writing to the target stream +for the anchor upload and also handles the return value from the stream. +Now, your application is called via the callback function that you may associate +with a request object. You indicate when you have sent all the data you want +by returning HT_LOADED from the callback. +*/ + +extern int HTUpload_callback (HTRequest * request, HTStream * target); -/* Generate the anchor for the home page -** ------------------------------------- -** -** As it involves file access, this should only be done once -** when the program first runs. -** This is a default algorithm -- browser don't HAVE to use this. -** +/* */ -extern HTParentAnchor * HTHomeAnchor NOPARAMS; + +#ifdef __cplusplus +} +#endif #endif /* HTACCESS_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTAlert.h b/Library/src/HTAlert.h index 508c9d35..1182838d 100644 --- a/Library/src/HTAlert.h +++ b/Library/src/HTAlert.h @@ -1,52 +1,331 @@ -/* */ +/* + + + W3C Sample Code Library libwww Library Alert Class + + +! + The Alert Class +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +The Alert class defines a set of methods to be used by libwww for passing +prompts and message to the application. In order to maintain libwww application +independent and natural language independent, it does not know how to communicate +with a user. Note here that a user is a somewhat abstract notion +for  something that can receive a message or prompt from libwww. A +user can for example be a person, but is may also be handled +automatically by a robot or a client receiving a response from a HTTP server. + +Libwww has a set of opcodes that classifies the nature of the message, +for example that it is a question that must be confirmed in order to continue +a request or simply a progress notification. The application can register +a callback for any number of the defined opcodes - in case libwww has a message +for an opcode that does not have a method associated, the message is ignored. +You can also globally disable any message send from libwww. + +Note: The library core does not define any message or dialog +methods - they are all considered part of the application. However, it comes +with a default set of methods which can be initiated +using the function HTAlertInit() in HTInit +module + +This module is implemented by HTAlert.c, and it is +a part of the W3C Sample Code +Library. +*/ + +#ifndef HTALERT_H +#define HTALERT_H + +#include "HTReq.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +. + Message Opcodes and Messages +. + +The callback functions are defined as a generic callback where the caller +can pass a set of input parameters and the callee can return a set of outptu +parameters. Also note that all the *_PROG_* opcodes are a subset +of HT_A_PROGRESS. This means that you easily can register a +callback for all progress reports. + +The callback handler for progress notifications SHOULD NOT be used +to interrupt the ongoing message as it is not guaranteed to be in a state +to do so. Instead you should use the event handlers +or the timers for this. +*/ + +typedef enum _HTAlertOpcode { + HT_PROG_DNS = 0x1, /* Doing DNS resolution */ + HT_PROG_CONNECT = 0x2, /* Connecting Active */ + HT_PROG_ACCEPT = 0x4, /* Connecting Passive */ + HT_PROG_READ = 0x8, /* Read data */ + HT_PROG_WRITE = 0x10, /* Write data */ + HT_PROG_DONE = 0x20, /* Request finished */ + HT_PROG_INTERRUPT = 0x40, /* Request interrupted */ + HT_PROG_OTHER = 0x80, /* Other progress notes */ + HT_PROG_TIMEOUT = 0x100, /* Request timed out */ + HT_PROG_LOGIN = 0x200, /* Automatic login notifications */ + HT_A_PROGRESS = 0xFFFF, /* Get all progress reports - no reply */ + + /* First word are reserved for progresss notifications */ + + HT_A_MESSAGE = 0x1<<16, /* Send a message - no reply */ + HT_A_CONFIRM = 0x2<<16, /* Want YES or NO back */ + HT_A_PROMPT = 0x4<<16, /* Want full dialog */ + HT_A_SECRET = 0x8<<16, /* Secret dialog (e.g. password) */ + HT_A_USER_PW = 0x10<<16 /* Atomic userid and password */ +} HTAlertOpcode; + +typedef struct _HTAlertPar HTAlertPar; -/* Displaying messages and getting input for WWW Library -** ===================================================== -** -** May 92 Created By C.T. Barker -** Feb 93 Portablized etc TBL +typedef BOOL HTAlertCallback (HTRequest * request, HTAlertOpcode op, + int msgnum, const char * dfault, void * input, + HTAlertPar * reply); + +/* + +If you don't expect any return values then reply can be NULL. +The return value of the callback function can be used to indicate confirmation +on a prompt (Yes or No). +. + User Prompts and Questions +. + +This is an enumerated list of messages that can be converted into a string +table etc. See the HTDialog module for +default initialization of these strings. +*/ + +typedef enum _HTAlertMsg { + HT_MSG_NULL = -1, + HT_MSG_UID = 0, + HT_MSG_PROXY_UID, + HT_MSG_FTP_UID, + HT_MSG_PW, + HT_MSG_FILENAME, + HT_MSG_ACCOUNT, + HT_MSG_METHOD, + HT_MSG_MOVED, + HT_MSG_RULES, + HT_MSG_FILE_REPLACE, + HT_MSG_RETRY_AUTHENTICATION, + HT_MSG_RETRY_PROXY_AUTH, + HT_MSG_REDO, + HT_MSG_BIG_PUT, + HT_MSG_SOURCE_MOVED, + HT_MSG_DESTINATION_MOVED, + HT_MSG_REDIRECTION, + HT_MSG_PROXY, + HT_MSG_CACHE_LOCK, + HT_MSG_ACCEPT_COOKIE, + HT_MSG_ELEMENTS /* This MUST be the last element */ +} HTAlertMsg; + +/* +. + Enable or Disable Messages +. + +If you really don't want the library to prompt for anything at all then enable +this constant. The default value is Interactive. +*/ + +extern void HTAlert_setInteractive (BOOL interative); +extern BOOL HTAlert_interactive (void); + +/* +. + Creation and Deletion Methods +. + +Message methods are registered in lists. By default a list is not enabled +before you assign it as being active. This allows +the application to maintain multiple lists of message handlers which can +be swapped in and out as neeeded. +( + Add a Callback Function +) + +Register a call back function that is to be called when generating messages, +dialog, prompts, progress reports etc. The opcode signifies which call back +function to call depending of the type of the message. Opcode can be any +combination of the bitflags defined by HTAlertOpcode. If you +register one callback for HT_A_PROGRESS then this will get called +on all progress notifications. */ -#include "HTUtils.h" -#include "tcp.h" +extern BOOL HTAlertCall_add (HTList * list, HTAlertCallback * cbf, + HTAlertOpcode opcode); + +/* +( + Delete a Callback function +) -/* Display a message and get the input -** -** On entry, -** Msg is the message. -** -** On exit, -** Return value is malloc'd string which must be freed. +Unregister a call back function from a list */ -extern char * HTPrompt PARAMS((CONST char * Msg, CONST char * deflt)); +extern BOOL HTAlertCall_delete (HTList * list, HTAlertCallback * cbf); -/* Display a message, don't wait for input -** -** On entry, -** The input is a list of parameters for printf. +/* +( + Delete all Callbacks With this Opcode +) + +Unregister all handlers registered for a given opcode. */ -extern void HTAlert PARAMS((CONST char * Msg)); +extern BOOL HTAlertCall_deleteOpcode (HTList * list, HTAlertOpcode opcode); + +/* +( + Delete a list of Callback Functions +) -/* Display a progress message for information (and diagnostics) only -** -** On entry, -** The input is a list of parameters for printf. +Unregisters all call back functions */ -extern void HTProgress PARAMS((CONST char * Msg)); +extern BOOL HTAlertCall_deleteAll (HTList * list); -/* Display a message, then wait for 'yes' or 'no'. -** -** On entry, -** Takes a list of parameters for printf. -** -** On exit, -** If the user enters 'YES', returns TRUE, returns FALSE -** otherwise. +/* +( + Find a Callback Function +) + +Finds a callback function corresponding to the opcode. If none has been +registered then NULL is returned. */ -extern BOOL HTConfirm PARAMS ((CONST char * Msg)); + +extern HTAlertCallback * HTAlertCall_find(HTList * list, HTAlertOpcode opcode); + /* +. + The Reply Object +. - */ +The reply object is used for communicating input from the user back +to the Library. This is only required to use when for example the user is +prompted for a file name etc. You can find several examples on how to use +this in the default message and dialog module +provided together with the Library. +*/ +extern HTAlertPar * HTAlert_newReply (void); +extern void HTAlert_deleteReply (HTAlertPar * old); + +/* +( + Handle the Reply Message +) + +These methods provide the API for handling the reply message. There are two +ways of assigning a message to the reply message - either by copying the +buffer or by reusing the same buffer. In the latter case, the caller must +make sure not to free the reply message before it has been used. +*/ + +extern BOOL HTAlert_setReplyMessage (HTAlertPar * me, const char *message); +extern BOOL HTAlert_assignReplyMessage (HTAlertPar * me, char * message); + +/* + +You can get the data back again by using this method: +*/ + +extern char * HTAlert_replyMessage (HTAlertPar * me); + +/* +*/ + +extern char * HTAlert_replySecret (HTAlertPar * me); +extern BOOL HTAlert_setReplySecret (HTAlertPar * me, const char * secret); + +extern void * HTAlert_replyOutput (HTAlertPar * me); +extern BOOL HTAlert_setReplyOutput (HTAlertPar * me, void * output); + +/* +. + Active set of Callback Functions +. + +A list can be assigned as being active in which case it is visible +for libwww by assigning the list as the global alert list. Libwww +does not know about inactive lists of alert handlers. +*/ + +extern void HTAlert_setGlobal (HTList * list); +extern HTList * HTAlert_global (void); + +/* +( + Global Alert List Methods +) + +You can assign a callback directly to the global list in which case it becomes +immediately available to libwww. In this case you do not need to worry about +creating the list - it will be created as well as deleted automatically. + + Add an Alert Handler + +*/ + +extern BOOL HTAlert_add (HTAlertCallback * cbf, HTAlertOpcode opcode); + +/* + + Delete an Alert Handler + + +You can either delete a handler by referring to its address or to the opcode +that it has been registered for. +*/ + +extern BOOL HTAlert_delete (HTAlertCallback * cbf); +extern BOOL HTAlert_deleteOpcode (HTAlertOpcode opcode); + +/* + + Delete all Alert Handlers + +*/ + +extern BOOL HTAlert_deleteAll (void); + +/* + + Find an Alert Handler + +*/ + +extern HTAlertCallback * HTAlert_find (HTAlertOpcode opcode); + +/* +*/ + +#ifdef __cplusplus +} +#endif + +#endif + +/* + + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTAnchor.h b/Library/src/HTAnchor.h index 64e152f7..d7c99923 100644 --- a/Library/src/HTAnchor.h +++ b/Library/src/HTAnchor.h @@ -1,297 +1,706 @@ -/* */ +/* + + + W3C Sample Code Library libwww Anchor Class + + +! + The Anchor Class +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +An anchor represents a region of a hypertext document which is linked to +another anchor in the same or a different document. Another name for anchors +would be URLs as an anchor represents all we know about a URL - including +where it points to and who points to it. Because the anchor objects +represent the part of the Web, the application has been in touch, it is often +useful to maintain the anchors throughout the lifetime of the application. +It would actually be most useful if we had persistent anchors so that an +application could build up a higher knowledge about the Web topology. + +.When to Escape and Unescape Addresses. + + +The URI escape policy in libwww is that all URIs created as +anchors must already have been escaped. The reason for this is that if +URIs are not escaped then the URI parser is not guaranteed to work as +expected. Imagine, for example, that you have a ":" in a +host name, then you could get something like this: +http://my:host:8000/ instead of http://my%3Ahost:8000/. -/* Hypertext "Anchor" Object HTAnchor.h -** ========================== -** -** An anchor represents a region of a hypertext document which is linked -** to another anchor in the same or a different document. + +Libwww provides support for escaping and unescaping +URIs using this set of APIs. + + +This module is implemented by HTAnchor.c, and it +is a part of the W3C Sample Code +Library. */ #ifndef HTANCHOR_H #define HTANCHOR_H -/* Version 0 (TBL) written in Objective-C for the NeXT browser */ -/* Version 1 of 24-Oct-1991 (JFG), written in C, browser-independant */ - -#include "HTList.h" -#include "HTAtom.h" - -#ifdef SHORT_NAMES -#define HTAnchor_findChild HTAnFiCh -#define HTAnchor_findChildAndLink HTAnFiLi -#define HTAnchor_findAddress HTAnFiAd -#define HTAnchor_delete HTAnDele -#define HTAnchor_makeLastChild HTAnMaLa -#define HTAnchor_parent HTAnPare -#define HTAnchor_setDocument HTAnSeDo -#define HTAnchor_document HTAnDocu -#define HTAnchor_setFormat HTAnSeFo -#define HTAnchor_format HTAnForm -#define HTAnchor_setIndex HTAnSeIn -#define HTAnchor_isIndex HTAnIsIn -#define HTAnchor_address HTAnAddr -#define HTAnchor_hasChildren HTAnHaCh -#define HTAnchor_title HTAnTitl -#define HTAnchor_setTitle HTAnSeTi -#define HTAnchor_appendTitle HTAnApTi -#define HTAnchor_link HTAnLink -#define HTAnchor_followMainLink HTAnFoMa -#define HTAnchor_followTypedLink HTAnFoTy -#define HTAnchor_makeMainLink HTAnMaMa -#endif +#ifdef __cplusplus +extern "C" { +#endif + + +/* +. + Types defined and used by the Anchor Object +. -/* Main definition of anchor -** ========================= -*/ - -typedef struct _HyperDoc HyperDoc; /* Ready for forward references */ -typedef struct _HTAnchor HTAnchor; -typedef struct _HTParentAnchor HTParentAnchor; - -/* After definition of HTFormat: */ -#include "HTFormat.h" - -typedef HTAtom HTLinkType; - -typedef struct { - HTAnchor * dest; /* The anchor to which this leads */ - HTLinkType * type; /* Semantics of this link */ -} HTLink; - -struct _HTAnchor { /* Generic anchor : just links */ - HTLink mainLink; /* Main (or default) destination of this */ - HTList * links; /* List of extra links from this, if any */ - /* We separate the first link from the others to avoid too many small mallocs - involved by a list creation. Most anchors only point to one place. */ - HTParentAnchor * parent; /* Parent of this anchor (self for adults) */ -}; - -struct _HTParentAnchor { - /* Common part from the generic anchor structure */ - HTLink mainLink; /* Main (or default) destination of this */ - HTList * links; /* List of extra links from this, if any */ - HTParentAnchor * parent; /* Parent of this anchor (self) */ - - /* ParentAnchor-specific information */ - HTList * children; /* Subanchors of this, if any */ - HTList * sources; /* List of anchors pointing to this, if any */ - HyperDoc * document; /* The document within which this is an anchor */ - char * address; /* Absolute address of this node */ - HTFormat format; /* Pointer to node format descriptor */ - BOOL isIndex; /* Acceptance of a keyword search */ - char * title; /* Title of document */ - - HTList* methods; /* Methods available as HTAtoms */ - void * protocol; /* Protocol object */ - char * physical; /* Physical address */ -}; - -typedef struct { - /* Common part from the generic anchor structure */ - HTLink mainLink; /* Main (or default) destination of this */ - HTList * links; /* List of extra links from this, if any */ - HTParentAnchor * parent; /* Parent of this anchor */ - - /* ChildAnchor-specific information */ - char * tag; /* Address of this anchor relative to parent */ -} HTChildAnchor; - - -/* Create new or find old sub-anchor -** --------------------------------- -** -** This one is for a new anchor being edited into an existing -** document. The parent anchor must already exist. -*/ - -extern HTChildAnchor * HTAnchor_findChild - PARAMS( - (HTParentAnchor *parent, - CONST char *tag) - ); - -/* Create or find a child anchor with a possible link -** -------------------------------------------------- -** -** Create new anchor with a given parent and possibly -** a name, and possibly a link to a _relatively_ named anchor. -** (Code originally in ParseHTML.h) -*/ -extern HTChildAnchor * HTAnchor_findChildAndLink - PARAMS(( - HTParentAnchor * parent, /* May not be 0 */ - CONST char * tag, /* May be "" or 0 */ - CONST char * href, /* May be "" or 0 */ - HTLinkType * ltype /* May be 0 */ - )); - - -/* Create new or find old named anchor -** ----------------------------------- -** -** This one is for a reference which is found in a document, and might -** not be already loaded. -** Note: You are not guaranteed a new anchor -- you might get an old one, -** like with fonts. -*/ - -extern HTAnchor * HTAnchor_findAddress - PARAMS( - (CONST char * address) - ); - - -/* Delete an anchor and possibly related things (auto garbage collection) -** -------------------------------------------- -** -** The anchor is only deleted if the corresponding document is not loaded. -** All outgoing links from parent and children are deleted, and this anchor -** is removed from the sources list of all its targets. -** We also try to delete the targets whose documents are not loaded. -** If this anchor's source list is empty, we delete it and its children. -*/ - -extern BOOL HTAnchor_delete - PARAMS( - (HTParentAnchor *me) - ); - - -/* Move an anchor to the head of the list of its siblings -** ------------------------------------------------------ -** -** This is to ensure that an anchor which might have already existed -** is put in the correct order as we load the document. -*/ - -extern void HTAnchor_makeLastChild - PARAMS( - (HTChildAnchor *me) - ); - -/* Data access functions -** --------------------- -*/ - -extern HTParentAnchor * HTAnchor_parent - PARAMS( - (HTAnchor *me) - ); - -extern void HTAnchor_setDocument - PARAMS( - (HTParentAnchor *me, HyperDoc *doc) - ); - -extern HyperDoc * HTAnchor_document - PARAMS( - (HTParentAnchor *me) - ); -/* We don't want code to change an address after anchor creation... yet ? -extern void HTAnchor_setAddress - PARAMS( - (HTAnchor *me, char *addr) - ); +This is a set of videly used type definitions used through out the Library: */ -/* Returns the full URI of the anchor, child or parent -** as a malloc'd string to be freed by the caller. +#include "WWWUtil.h" + +typedef HTAtom * HTFormat; +typedef HTAtom * HTLevel; /* Used to specify HTML level */ +typedef HTAtom * HTEncoding; /* C-E and C-T-E */ +typedef HTAtom * HTCharset; +typedef HTAtom * HTLanguage; + +typedef struct _HTAnchor HTAnchor; +typedef struct _HTParentAnchor HTParentAnchor; +typedef struct _HTChildAnchor HTChildAnchor; + +#include "HTLink.h" +#include "HTMethod.h" +#include "HTResponse.h" + +/* +. + The Anchor Class +. + +We have three variants of the Anchor object - I guess some would call them +superclass and subclasses ;-) +( + Anchor Base Class +) + +This is the super class of anchors. We often use this as an argument to the +functions that both accept parent anchors and child anchors. We separate +the first link from the others to avoid too many small mallocs involved by +a list creation. Most anchors only point to one place. +( + Anchor for a Parent Object +) + +These anchors points to the whole contents of any resource accesible by a +URI. The parent anchor now contains all known metainformation about that +object and in some cases the parent anchor also contains the document itself. +Often we get the metainformation about a document via the entity headers +in the HTTP specification. +( + Anchor for a Child Object +) + +A child anchor is a anchor object that points to a subpart of a hypertext +document. In HTML this is represented by the NAME tag of the +Anchor element. + +After we have defined the data structures we must define the methods that +can be used on them. All anchors are kept in an internal hash table so that +they are easier to find again. +( + Find/Create a Parent Anchor +) + +This one is for a reference (link) which is found in a document, and might +not be already loaded. The parent anchor returned can either be created on +the spot or is already in the hash table. */ -extern char * HTAnchor_address - PARAMS( - (HTAnchor *me) - ); -extern void HTAnchor_setFormat - PARAMS( - (HTParentAnchor *me, HTFormat form) - ); +extern HTAnchor * HTAnchor_findAddress (const char * address); + +/* +( + Find/Create a Child Anchor +) + +This one is for a new child anchor being edited into an existing document. +The parent anchor must already exist but the child returned can either be +created on the spot or is already in the hash table. The tag is +the part that's after the '#' sign in a URI. +*/ -extern HTFormat HTAnchor_format - PARAMS( - (HTParentAnchor *me) - ); +extern HTChildAnchor * HTAnchor_findChild (HTParentAnchor *parent, + const char * tag); -extern void HTAnchor_setIndex - PARAMS( - (HTParentAnchor *me) - ); +/* +( + Find/Create a Child Anchor and Link to Another Parent +) + +Find a child anchor anchor with a given parent and possibly a tag, +and (if passed) link this child to the URI given in the href. As +we really want typed links to the caller should also indicate what the type +of the link is (see HTTP spec for more information). The link is +relative to the address of the parent anchor. +*/ -extern BOOL HTAnchor_isIndex - PARAMS( - (HTParentAnchor *me) - ); +extern HTChildAnchor * HTAnchor_findChildAndLink ( + HTParentAnchor * parent, /* May not be 0 */ + const char * tag, /* May be "" or 0 */ + const char * href, /* May be "" or 0 */ + HTLinkType ltype); /* May be 0 */ -extern BOOL HTAnchor_hasChildren - PARAMS( - (HTParentAnchor *me) - ); +/* +( + Delete an Anchor +) -/* Title handling +All outgoing links from parent and children are deleted, and this anchor +is removed from the sources list of all its targets. We also delete the targets. +If this anchor's source list is empty, we delete it and its children. */ -extern CONST char * HTAnchor_title - PARAMS( - (HTParentAnchor *me) - ); -extern void HTAnchor_setTitle - PARAMS( - (HTParentAnchor *me, CONST char * title) - ); +extern BOOL HTAnchor_delete (HTParentAnchor *me); + +/* +( + Clear all Anchors +) + +Deletes all the metadata associated with anchors but doesn't delete +the anchor link structure itself. This is much safer than deleting the +complete anchor structure as this represents the complete Web the +application has been in touch with. It also returns a list of all the +objects (hyperdoc) hanging of the parent anchors found while doing +it. These are not deleted by libwww. +*/ -extern void HTAnchor_appendTitle - PARAMS( - (HTParentAnchor *me, CONST char * title) - ); +extern BOOL HTAnchor_clearAll (HTList * documents); -/* Link this Anchor to another given one -** ------------------------------------- +/* +( + Delete all Anchors +) + +Deletes all anchors and return a list of all the objects (hyperdoc) +hanging of the parent anchors found while doing it. The application may keep +its own list of HyperDocs, but this function returns it anyway. +It is always for the application to delete any +HyperDocs. If NULL then no hyperdocs are returned. Return YES +if OK, else NO. + +Note: This function is different from cleaning up the history list! */ -extern BOOL HTAnchor_link - PARAMS( - (HTAnchor *source, HTAnchor *destination, HTLinkType *type) - ); +extern BOOL HTAnchor_deleteAll (HTList * objects); + +/* +( + Flatten all anchors into Array +) + +Flattens the anchor web structure into an array. This is useful for +calculating statistics, sorting the parent anchors etc. + +The caller can indicate the size of the array (total number of anchors +if known - otherwise 0). + +Return an array that must be freed by the caller or NULL if no +anchors. -/* Manipulation of links -** --------------------- */ -extern HTAnchor * HTAnchor_followMainLink - PARAMS( - (HTAnchor *me) - ); +extern HTArray * HTAnchor_getArray (int growby); + +/* -extern HTAnchor * HTAnchor_followTypedLink - PARAMS( - (HTAnchor *me, HTLinkType *type) - ); +. + Links and Anchors +. -extern BOOL HTAnchor_makeMainLink - PARAMS( - (HTAnchor *me, HTLink *movingLink) - ); +Anchor objects are bound together by Link objects +that carry information about what type of link and whetther we have followed +the link etc. Any anchor object can have zero, one, or many links but the +normal case is one. Therefore we treat this is a special way. +( + Handling the Main Link +) -/* Read and write methods -** ---------------------- +Any outgoing link can at any time be the main destination. */ -extern HTList * HTAnchor_methods PARAMS((HTParentAnchor *me)); -/* Protocol -** -------- +extern BOOL HTAnchor_setMainLink (HTAnchor * anchor, HTLink * link); +extern HTLink * HTAnchor_mainLink (HTAnchor * anchor); + +extern HTAnchor * HTAnchor_followMainLink (HTAnchor * anchor); + +/* +( + Handling the Sub Links +) */ -extern void * HTAnchor_protocol PARAMS((HTParentAnchor * me)); -extern void HTAnchor_setProtocol PARAMS((HTParentAnchor * me, - void* protocol)); -/* Physical address -** ---------------- +extern BOOL HTAnchor_setSubLinks (HTAnchor * anchor, HTList * list); +extern HTList * HTAnchor_subLinks (HTAnchor * anchor); + +/* + +( + Search for a Link Type +) + +Links can have relations (indicated by the "rel" or "rev" HTML link +attributes). This function can search an anchor looking for a +specific type, for example "stylesheet". + */ -extern char * HTAnchor_physical PARAMS((HTParentAnchor * me)); -extern void HTAnchor_setPhysical PARAMS((HTParentAnchor * me, - char * protocol)); + +extern HTLink * HTAnchor_findLinkType (HTAnchor * me, HTLinkType type); + +/* + +. + Relations Between Children and Parents +. + +As always, children and parents have a compliated relationship and the libwww +Anchor class is no exception. +( + Who is Parent? +) + +For parent anchors this returns the anchor itself +*/ +extern HTParentAnchor * HTAnchor_parent (HTAnchor *me); + +/* +( + Does it have any Anchors within it? +) + +Does this parent anchor have any children +*/ +extern BOOL HTAnchor_hasChildren (HTParentAnchor *me); + +/* +( + Is this anchor a Child? +) +*/ + +extern BOOL HTAnchor_isChild (HTAnchor * me); + +/* + +( + Get the Tag/Fragment/View of this anchor +) + +If this is a child anchor then it has a tag (often also called a "fragment"), which +is essentially a specific view of a document. This is why I like to call it +a view instead of a fragment. The string returned (if non-NULL) must be freed by the +caller. + +*/ + +extern char * HTAnchor_view (HTAnchor * me); + +/* + +. + Anchor Addresses +. + +There are two addresses of an anchor. The URI that was passed when the anchor +was crated and the physical address that's used when the URI is going to +be requested. The two addresses may be different if the request is going +through a proxy or a gateway or it may have been mapped through a rule file. +( + Logical Address +) + +Returns the full URI of the anchor, child or parent as a malloc'd string +to be freed by the caller as when the anchor was created. +*/ +extern char * HTAnchor_address (HTAnchor * me); + +/* +( + Expanded Logical Address +) + +When expanding URLs within a hypertext document, the base address is taken +as the following value if present (in that order): + + o + Content-Base header + o + Content-Location header + o + Logical address + + */ +extern char * HTAnchor_expandedAddress (HTAnchor * me); + +/* +( + Physical address +) + +Contains the physical address after we haved looked for proxies etc. +*/ +extern char * HTAnchor_physical (HTParentAnchor * me); +extern void HTAnchor_setPhysical (HTParentAnchor * me, char * protocol); +extern void HTAnchor_clearPhysical (HTParentAnchor * me); + +/* +. + Entity Body Information +. + +A parent anchor can have a data object bound to it. This data object does +can for example be a parsed version of a HTML that knows how to present itself +to the user, or it can be an unparsed data object. It's completely free for +the application to use this possibility, but a typical usage would to manage +the data object as part of a memory cache. +*/ + +extern void HTAnchor_setDocument (HTParentAnchor *me, void * doc); +extern void * HTAnchor_document (HTParentAnchor *me); + +/* +. + Entity Header Information +. + +The anchor object also contains all the metainformation that we know about +the object. +( + Clear All header Information +) +*/ + +extern void HTAnchor_clearHeader (HTParentAnchor *me); + +/* +( + Inherit Metainformation from the Response object +) + +Once we have decided to cache the object we transfer already parsed +metainformation from the HTResponse object to +the anchor object and also the unparsed headers as we may wanna use that +information later. +*/ + +extern BOOL HTAnchor_update (HTParentAnchor * me, HTResponse * response); + +/* +( + Is the Anchor searchable? +) +*/ +extern void HTAnchor_clearIndex (HTParentAnchor * me); +extern void HTAnchor_setIndex (HTParentAnchor * me); +extern BOOL HTAnchor_isIndex (HTParentAnchor * me); + +/* +( + Anchor Title +) + +We keep the title in the anchor as we then can refer to it later in the history +list etc. We can also obtain the title element if it is passed as a HTTP +header in the response. Any title element found in an HTML document will +overwrite a title given in a HTTP header. +*/ +extern const char * HTAnchor_title (HTParentAnchor *me); +extern void HTAnchor_setTitle (HTParentAnchor *me, + const char * title); +extern void HTAnchor_appendTitle (HTParentAnchor *me, + const char * title); + +/* +( + Meta Tags within the Document +) + +*/ + +extern HTAssocList * HTAnchor_meta (HTParentAnchor * me); +extern BOOL HTAnchor_addMeta (HTParentAnchor * me, + const char * name, const char * value); + +/* + + + The Robots Meta tag + + +A special case function that looks for any robots meta tag. This tag +contains information about which links a robot can traverse and which +it shouldn't. + +*/ + +extern char * HTAnchor_robots (HTParentAnchor * me); + +/* + +( + Content Base +) + +The Content-Base header may be used for resolving +relative URLs within the entity. If it there is no +Content-Base header then we use the Content-Location if +present and absolute. +*/ + +extern char * HTAnchor_base (HTParentAnchor * me); +extern BOOL HTAnchor_setBase (HTParentAnchor * me, char * base); + +/* +( + Content Location +) + +Content location can either be an absolute or a relative URL. The URL may +be either absolute or relative. If it is relative then we parse it relative +to the Content-Base header of the request URI if any, otherwise +we use the Request URI. +*/ + +extern char * HTAnchor_location (HTParentAnchor * me); +extern BOOL HTAnchor_setLocation (HTParentAnchor * me, char * location); + +/* +( + Media Types (Content-Type) +) +*/ + +extern HTFormat HTAnchor_format (HTParentAnchor *me); +extern void HTAnchor_setFormat (HTParentAnchor *me, + HTFormat form); + +/* +( + Content Type Parameters +) + +The Anchor obejct stores all content parameters in an Association list so +here you will always be able to find them. We also have a few methods for +the special cases: charset and level as they are +often needed. +*/ + +extern HTAssocList * HTAnchor_formatParam (HTParentAnchor * me); + +extern BOOL HTAnchor_addFormatParam (HTParentAnchor * me, + const char * name, const char * value); + +/* + + Charset parameter to Content-Type + +*/ + +extern HTCharset HTAnchor_charset (HTParentAnchor *me); +extern BOOL HTAnchor_setCharset (HTParentAnchor *me, + HTCharset charset); + +/* + + Level parameter to Content-Type + +*/ + +extern HTLevel HTAnchor_level (HTParentAnchor * me); +extern BOOL HTAnchor_setLevel (HTParentAnchor * me, + HTLevel level); + +/* +( + Content Language +) +*/ + +extern HTList * HTAnchor_language (HTParentAnchor * me); +extern BOOL HTAnchor_addLanguage (HTParentAnchor *me, HTLanguage lang); +extern BOOL HTAnchor_deleteLanguageAll (HTParentAnchor * me); + +/* +( + Content Encoding +) +*/ + +extern HTList * HTAnchor_encoding (HTParentAnchor * me); +extern BOOL HTAnchor_addEncoding (HTParentAnchor * me, HTEncoding enc); +extern BOOL HTAnchor_deleteEncoding (HTParentAnchor * me, HTEncoding enc); +extern BOOL HTAnchor_deleteEncodingAll (HTParentAnchor * me); + +#define HTAnchor_removeEncoding(a, e) HTAnchor_deleteEncoding((a), (e)) + +/* +( + Content Transfer Encoding +) +*/ + +extern HTEncoding HTAnchor_contentTransferEncoding (HTParentAnchor *me); +extern void HTAnchor_setContentTransferEncoding (HTParentAnchor *me, + HTEncoding cte); + +/* +( + Content Length +) +*/ + +extern long int HTAnchor_length (HTParentAnchor * me); +extern void HTAnchor_setLength (HTParentAnchor * me, long int length); +extern void HTAnchor_addLength (HTParentAnchor * me, long int deltalength); + +/* +( + Content MD5 +) +*/ + +extern char * HTAnchor_md5 (HTParentAnchor * me); +extern BOOL HTAnchor_setMd5 (HTParentAnchor * me, const char * hash); + +/* +( + Allowed methods (Allow) +) +*/ + +extern HTMethod HTAnchor_allow (HTParentAnchor * me); +extern void HTAnchor_setAllow (HTParentAnchor * me, HTMethod methodset); +extern void HTAnchor_appendAllow (HTParentAnchor * me, HTMethod methodset); + +/* +( + Version +) +*/ + +extern char * HTAnchor_version (HTParentAnchor * me); +extern void HTAnchor_setVersion (HTParentAnchor * me, const char * version); + +/* +( + Date +) + +Returns the date that was registered in the RFC822 header "Date" +*/ + +extern time_t HTAnchor_date (HTParentAnchor * me); +extern void HTAnchor_setDate (HTParentAnchor * me, const time_t date); + +/* +( + Last Modified Date +) + +Returns the date that was registered in the RFC822 header "Last-Modified" +*/ + +extern time_t HTAnchor_lastModified (HTParentAnchor * me); +extern void HTAnchor_setLastModified (HTParentAnchor * me, const time_t lm); + +/* +( + Entity Tag +) + +Entity tags are used for comparing two or more entities from the same requested +resource. It is a cache validator much in the same way Date can be. +The difference is that we can't always trust the date and time stamp and +hence we must have something stronger. +*/ +extern char * HTAnchor_etag (HTParentAnchor * me); +extern void HTAnchor_setEtag (HTParentAnchor * me, const char * etag); +extern BOOL HTAnchor_isEtagWeak (HTParentAnchor * me); + +/* +( + Age Header +) + +The Age response-header field conveys the sender's estimate +of the amount of time since the response (or its revalidation) was generated +at the origin server. A cached response is "fresh" if its age does not exceed +its freshness lifetime. +*/ + +extern time_t HTAnchor_age (HTParentAnchor * me); +extern void HTAnchor_setAge (HTParentAnchor * me, const time_t age); + +/* +( + Expires Date +) +*/ + +extern time_t HTAnchor_expires (HTParentAnchor * me); +extern void HTAnchor_setExpires (HTParentAnchor * me, const time_t exp); + +/* +( + Derived from +) +*/ + +extern char * HTAnchor_derived (HTParentAnchor *me); +extern void HTAnchor_setDerived (HTParentAnchor *me, const char *derived_from); + +/* +. + Status of Header Parsing +. + +This is primarily for internal use. It is so that we can check whether the +header has been parsed or not. +*/ + +extern BOOL HTAnchor_headerParsed (HTParentAnchor *me); +extern void HTAnchor_setHeaderParsed (HTParentAnchor *me); + +/* +( + Original Response Headers +) + +The MIME parser may add the original response headers +as (name,value) pairs. +*/ + +extern BOOL HTAnchor_setHeader (HTParentAnchor * me, HTAssocList * list); +extern HTAssocList * HTAnchor_header (HTParentAnchor * me); + +/* +*/ + +#ifdef __cplusplus +} +#endif #endif /* HTANCHOR_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTAtom.h b/Library/src/HTAtom.h index b2e454ea..d1d95144 100644 --- a/Library/src/HTAtom.h +++ b/Library/src/HTAtom.h @@ -1,42 +1,109 @@ -/* */ - -/* Atoms: Names to numbers HTAtom.h -** ======================= -** -** Atoms are names which are given representative pointer values -** so that they can be stored more efficiently, and compaisons -** for equality done more efficiently. -** -** HTAtom_for(string) returns a representative value such that it -** will always (within one run of the program) return the same -** value for the same given string. -** -** Authors: -** TBL Tim Berners-Lee, WorldWideWeb project, CERN -** -** (c) Copyright CERN 1991 - See Copyright.html -** +/* + + + W3C Sample Code Library libwww Atom Class + + +! + The Atom Class +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +The Atom Class defines strings which are given representative +pointer values so that they can be stored more efficiently, and comparisons +for equality done more efficiently. The list of atoms is stored +in a hash table, so when asking for a new atom you might in fact get back an +existing one. + +Note: There are a whole bunch of +MIME-types defined as +atoms, so please use them! + +This module is implemented by HTAtom.c, and it is +a part of the W3C Sample Code +Library. */ #ifndef HTATOM_H #define HTATOM_H +#include "HTList.h" + +#ifdef __cplusplus +extern "C" { +#endif + typedef struct _HTAtom HTAtom; struct _HTAtom { - HTAtom * next; - char * name; + HTAtom * next; + char * name; }; /* struct _HTAtom */ +/* +( + Get an Atom +) + +This function returns a representative value (an atom) such +that it will always (within one run of the program) return the same value +for the same given string. The former is case sensitive, the latter is case +insensitive. +*/ + +extern HTAtom * HTAtom_for (const char * string); +extern HTAtom * HTAtom_caseFor (const char * string); -#ifdef __STDC__ -extern HTAtom * HTAtom_for(const char * string); -#else -extern HTAtom * HTAtom_for(); +/* +( + Get Content of an Atom +) +*/ + +#define HTAtom_name(a) ((a) ? (a)->name : NULL) + +/* + +This macro returns the string pointed to by the atom. +( + Search For Atoms +) + +Returns a list of atoms which matches the template given. It +is especially made for MIME-types so that for example a template like +text returns a list of all MIME-types +of type text. +*/ + +extern HTList * HTAtom_templateMatches (const char * templ); + +/* +( + Cleanup Memory +) + +In order to cleanup memory, call this function. This is done automaticly +from the HTLibTerminate function. +*/ + +extern void HTAtom_deleteAll (void); + +#ifdef __cplusplus +} #endif -#define HTAtom_name(a) ((a)->name) +#endif -#endif /* HTATOM_H */ /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTBTree.h b/Library/src/HTBTree.h index f4a0dce9..b7c84561 100644 --- a/Library/src/HTBTree.h +++ b/Library/src/HTBTree.h @@ -1,66 +1,120 @@ -/* Balanced Binary Tree for sorting things HTBTree.h -** ======================================= -** -** Tree createion, trversal and freeing. User-supplied -** comparison routine. +/* + + W3C Sample Code Library libwww Balanced Binary Tree + + + + +!Balanced Binary Tree! + +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +Tree creation, traversal and freeing. User-supplied comparison +routine. + +This module is implemented by HTBTree.c, and +it is a part of the W3C +Sample Code Library. + +*/ + +#ifndef HTBTTEE_H +#define HTBTREE_H + +#include "HTArray.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + +*/ + +typedef struct _HTBTree HTBTree; + +typedef struct _HTBTree_element HTBTElement; + +/* + +.Create a Binary Tree. + +This function creates a new binary tree and uses the comparison +function when building the tree. + */ +extern HTBTree * HTBTree_new (HTComparer * comp); -typedef struct _HTBTree_element { - void *object; /* User object */ - struct _HTBTree_element *up; - struct _HTBTree_element *left; - int left_depth; - struct _HTBTree_element *right; - int right_depth; -} HTBTElement; +/* -typedef (int *HTComparer) PARAMS((void * a, void * b)); +.Free storage of the tree but not of the objects. -typedef struct _HTBTree_top { - HTComparer compare; - struct _HTBTree_element *top; -} HTBTree; +*/ + +extern void HTBTree_free (HTBTree * tree); + +/* +.Free storage of the tree and of the objects. -/* Create a binary tree given its discrimination routine -** ----------------------------------------------------- */ -extern HTBTree * HTBTree_new PARAMS((HTComparer comp)); +extern void HTBTreeAndObject_free (HTBTree * tree); +/* + +.Add an object to a binary tree. -/* Free storage -** ------------ */ -extern void HTBTree_free PARAMS((HTBTree* tree)); +extern void HTBTree_add (HTBTree* tree, void * object); + +/* + +.Return an Object. -/* Add an object to a binary tree -** ------------------------------ */ -extern void HTBTree_add PARAMS((HTBTree* tree, void * object)); +extern void * HTBTree_object (HTBTElement * element); + +/* + +.Find next element in depth-first order. +(On entry,) + +If element is NULL then start with leftmost element. if +not NULL then give next object to the right. The function returns a +pointer to element or NULL if none left. -/* Find user object for element -** --------------------------- */ -#define HTBTree_object(element) ((element)->object) +extern HTBTElement * HTBTree_next (HTBTree * tree, HTBTElement * element); +/* -/* Find next element in depth-first order -** ------------------------------------- -** -** On entry, -** ele if NULL, start with leftmost element. -** if != 0 give next object to the right. -** -** returns Pointer to element ot NULL if none left. -** */ -extern HTBTElement * HTBTree_next PARAMS((HTBTree* tree, HTBTElement * ele)); +#ifdef __cplusplus +} +#endif + +#endif /* HTBTTEE_H */ +/* + + +@(#) $Id$ + + +*/ diff --git a/Library/src/HTChunk.h b/Library/src/HTChunk.h index 1b6dda36..3a3bb9d9 100644 --- a/Library/src/HTChunk.h +++ b/Library/src/HTChunk.h @@ -1,113 +1,244 @@ -/* */ +/* + + + W3C Sample Code Library libwww Chunk Class -/* Chunk handling: Flexible arrays -** =============================== -** -** This module implements a flexible array. It is a general utility module. -** A chunk is a structure which may be extended. These routines create -** and append data to chnuks, automatically reallocating them as necessary. -** + +! + The Chunk Class +! */ +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ -typedef struct { - int size; /* In bytes */ - int growby; /* Allocation unit in bytes */ - int allocated; /* Current size of *data */ - char * data; /* Pointer to malloced area or 0 */ -} HTChunk; +/* +The Chunk Class defines a way to automatically handle dynamic strings and +other data types. You create a chunk with an initial size and it will then +automatically grow to accommodate added data to the chunk. It is a general +utility module. It is guaranteed that the array is '\0' terminated +at all times (and hence is a valid C type string). The method +HTChunkTerminate can be used to explicitly +add a terminating '\0' and then to include this character in +the chunk size. If left out, the terminating character is not considered +part of the chunk. + +Note: The names without a "_" (made as a #define's) are +only provided for backwards compatibility and should not be used. + +This module is implemented by HTChunk.c, and it is +a part of the W3C Sample Code +Library. +*/ -#ifdef SHORT_NAMES -#define HTChunkClear HTChClea -#define HTChunkPutc HTChPutc -#define HTChunkPuts HTChPuts -#define HTChunkCreate HTChCrea -#define HTChunkTerminate HTChTerm -#define HTChunkEnsure HtChEnsu -#endif +#ifndef HTCHUNK_H +#define HTCHUNK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* +. + Create new chunk +. + +Create a new chunk and specify the number of bytes to allocate at a time +when the chunk is later extended. Arbitrary but normally a trade-off time +vs. memory +*/ + +typedef struct _HTChunk HTChunk; + +extern HTChunk * HTChunk_new (int growby); + +/* +. + Free a chunk +. + +Free a chunk created by HTChunk_newfrom memory +*/ + +extern void HTChunk_delete (HTChunk * ch); + +/* +. + Clear a chunk +. + +Keep the chunk in memory but clear all data kept inside. This can be used +if you know that you can reuse the allocated memory instead of allocating +new memory. This zeros out all the allocated data (even data past the +indicated size) and sets the size of the chunk to 0. If you have not used +any bytes past the indicated size, it is more efficient to truncate the +chunk to 0 instead. +*/ + +extern void HTChunk_clear (HTChunk * ch); + +/* +. + Ensure a Chunk has a Certain Amount of Free Space +. + +Make sure that a chunk has enough memory allocated to grow by the +indicated extra size. If this is not the case, then the chunk is expanded +(in multiples of the chunk's "growby" size). Nothing is done if the +current size plus the requested extra space fits within the chunk's +currently allocated memory. +*/ + +extern void HTChunk_ensure (HTChunk * ch, int extra_size); + +/* +. + Append a character to a chunk +. + +Add the character and increment the size of the chunk by one character +*/ + +extern void HTChunk_putc (HTChunk * ch, char c); +/* +. + Append a string to a chunk +. -/* Create new chunk -** -** On entry, -** -** growby The number of bytes to allocate at a time -** when the chunk is later extended. Arbitrary but -** normally a trade-off time vs. memory -** -** On exit, -** returns A chunk pointer to the new chunk, +Add the string and increment the size of the chunk by the length of the string +(without the trailing zero) */ -extern HTChunk * HTChunkCreate PARAMS((int growby)); +extern void HTChunk_puts (HTChunk * ch, const char *str); + +/* +. + Append a block to a chunk +. -/* Free a chunk -** -** On entry, -** ch A valid chunk pointer made by HTChunkCreate() -** -** On exit, -** ch is invalid and may not be used. +Add the block and increment the size of the chunk by the len */ -extern void HTChunkFree PARAMS((HTChunk * ch)); +extern void HTChunk_putb (HTChunk * ch, const char *block, int len); + + +/* +. + Return Pointer to Data +. -/* Clear a chunk -** -** On entry, -** ch A valid chunk pointer made by HTChunkCreate() -** -** On exit, -** *ch The size of the chunk is zero. +This define converts a chunk to a normal char pointer so that it can be parsed +to any ANSI C string function. */ -extern void HTChunkClear PARAMS((HTChunk * ch)); +extern char * HTChunk_data (HTChunk * ch); -/* Ensure a chunk has a certain space in -** -** On entry, -** ch A valid chunk pointer made by HTChunkCreate() -** s The size required -** -** On exit, -** *ch Has size at least s +/* +. + Return Current Size +. + +Returns the current size of the chunk */ -extern void HTChunkEnsure PARAMS((HTChunk * ch, int s)); +extern int HTChunk_size (HTChunk * ch); -/* Append a character to a chunk -** -** On entry, -** ch A valid chunk pointer made by HTChunkCreate() -** c The character to be appended -** On exit, -** *ch Is one character bigger +/* +. + Setting the Size of a Chunk +. + +If you want to cut off a piece of a chunk or extend it to make room +for some direct buffer manipulation, then you can use one of these +functions. Both of these calls set the size of the chunk to be +size, but the truncate call only allows you to make the +string shorter. If the string is made shorter, the formerly-used bytes +are cleared, so truncating a chunk to 0 is analogous to clearing it, +but slightly more efficient. */ -extern void HTChunkPutc PARAMS((HTChunk * ch, char c)); +extern BOOL HTChunk_truncate (HTChunk * ch, int size); +extern BOOL HTChunk_setSize (HTChunk * ch, int size); -/* Append a string to a chunk -** -** On entry, -** ch A valid chunk pointer made by HTChunkCreate() -** s Tpoints to a zero-terminated string to be appended -** On exit, -** *ch Is bigger by strlen(s) +/* +. + Zero Terminate a chunk +. + +As a chunk often is a dynamic string, it needs to be terminated by a zero +in order to be used in C. However, by default any chunk is +always zero terminated, so the only purpose of this function is to +increment the size counter with one corresponding to the zero. */ -extern void HTChunkPuts PARAMS((HTChunk * ch, const char *s)); +extern void HTChunk_terminate (HTChunk * ch); +/* +. + CString Conversions +. + +A Chunk may be built from an allocated string. The chunk assumes control +of the passed string, eliminating the need for additional allocations and +string copies. +When you take control of the CString from a chunk, the chunk is destroyed. +*/ -/* Append a zero character to a chunk -** -** On entry, -** ch A valid chunk pointer made by HTChunkCreate() -** On exit, -** *ch Is one character bigger +extern HTChunk * HTChunk_fromCString (char * str, int grow); +extern char * HTChunk_toCString (HTChunk * ch); + +/* +. + Creating a Chunk from an allocated buffer +. + +A Chunk may be built from an allocted buffer. You must specify how much +memory is allocated in the buffer (buflen) and what the size the new +Chunk should be (size). All memory between size and buflen is zeroed. +Note that is is legal to specify a size equal to the buflen if you don't +expect the Chunk to be null terminated. The chunk takes control of the +memory, and will free it when the Chunk is destroyed. Note that in order +to avoid conflicts, the buffer's memory should be allocated using +libwww's dedicated functions. */ -extern void HTChunkTerminate PARAMS((HTChunk * ch)); +extern HTChunk * HTChunk_fromBuffer (char * buf, int buflen, int size, int grow); + +/* +. + Old Interface Names +. + +Don't use these in new applications +*/ + +#define HTChunkCreate(growby) HTChunk_new(growby) +#define HTChunkFree(ch) HTChunk_delete(ch) +#define HTChunkClear(ch) HTChunk_clear(ch) +#define HTChunkEnsure(ch, s) HTChunk_ensure((ch), (s)) +#define HTChunkPutc(ch, c) HTChunk_putc((ch), (c)) +#define HTChunkPuts(ch, str) HTChunk_puts((ch), (str)) +#define HTChunkTerminate(ch) HTChunk_terminate(ch) +#define HTChunkData(ch) HTChunk_data(ch) +#define HTChunkSize(ch) HTChunk_size(ch) + /* +*/ - */ +#ifdef __cplusplus +} +#endif + +#endif /* HTCHUNK_H */ + +/* + + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTFTP.h b/Library/src/HTFTP.h index 9322a942..47662438 100644 --- a/Library/src/HTFTP.h +++ b/Library/src/HTFTP.h @@ -1,46 +1,113 @@ -/* */ +/* + + W3C Sample Code Library libwww FTP CLIENT + + + -/* FTP access functions HTFTP.h -** ==================== + +!FTP access functions! + +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. */ +/* + +This is the FTP load module that handles all communication with +FTP-servers. + +This module is implemented by HTFTP.c, and it is +a part of the W3C +Sample Code Library. + +*/ #ifndef HTFTP_H #define HTFTP_H +#include "HTProt.h" -#include "HTAnchor.h" -#include "HTStream.h" +#ifdef __cplusplus +extern "C" { +#endif + +extern HTProtCallback HTLoadFTP; + +typedef enum _FTPServerType { + FTP_GENERIC = 0x1, + FTP_MACHTEN = 0x2, + FTP_UNIX = 0x4, + FTP_VMS = 0x8, + FTP_CMS = 0x10, + FTP_DCTS = 0x20, + FTP_TCPC = 0x40, + FTP_PETER_LEWIS = 0x80, + FTP_NCSA = 0x200, + FTP_WINNT = 0x400, + FTP_UNSURE = 0x8000 +} FTPServerType; + +#define MAX_FTP_LINE 128 /* Don't use more than this */ + +/* + +. + Global Transfer Mode +. + +Can be used to set the default transfer mode overruling what may be +indicated in the FTP URL. +Added by Neil Griffin, GAIN Software -/* Retrieve File from Server -** ------------------------- -** -** On exit, -** returns Socket number for file if good. -** <0 if bad. */ -extern int HTFTPLoad -PARAMS -(( - CONST char * name, - HTParentAnchor * anchor, - HTFormat format_out, - HTStream* sink -)); - -/* Close socket opened for reading a file, and get final message -** ------------------------------------------------------------- -** + +typedef enum _FTPTransferMode { + FTP_DEFAULT_TRANSFER_MODE = 0, + FTP_ASCII_TRANSFER_MODE = 1, + FTP_BINARY_TRANSFER_MODE = 2, + FTP_DIR_TRANSFER_MODE = 3 +} FTPTransferMode; + +extern FTPTransferMode HTFTP_transferMode (void); +extern void HTFTP_setTransferMode (FTPTransferMode mode); + +/* + +. + Global Control Mode +. + +Can be used to set the default control modes for various FTP settings +like always aski for user name and password, etc. + */ -/*extern int HTFTP_close_file PARAMS ((int soc)); */ +typedef enum _FTPControlMode { + FTP_DEFAULT_CONTROL_MODE = 0, + FTP_ALWAYS_ASK_UID_PW = 1 +} FTPControlMode; + +extern FTPControlMode HTFTP_controlMode (void); +extern void HTFTP_setControlMode (FTPControlMode mode); + +/* -/* Return Host Name -** ---------------- */ -extern CONST char * HTHostName -NOPARAMS; +#ifdef __cplusplus +} #endif + +#endif /* HTFTP_H */ + /* - */ + + +@(#) $Id$ + + +*/ diff --git a/Library/src/HTFile.h b/Library/src/HTFile.h index 467995a9..399fb7f8 100644 --- a/Library/src/HTFile.h +++ b/Library/src/HTFile.h @@ -1,153 +1,120 @@ -/* */ +/* + + + + W3C Sample Code Library libwww Local File Access -/* File Access HTFile.h -** =========== -** -** These are routines for file access used by WWW browsers. -** + +! + Local File Access +! */ -#ifndef HTFILE_H -#define HTFILE_H +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ -#include "HTFormat.h" -#include "HTAccess.h" +/* +These are routines for local file access used by WWW browsers and servers. -/* Controlling globals +This module is implemented by HTFile.c, and it is +a part of the W3C Sample Code +Library. */ -extern int HTDirAccess; /* Directory access level */ -#define HT_DIR_FORBID 0 /* Altogether forbidden */ -#define HT_DIR_SELECTIVE 1 /* If .www_browsable exists */ -#define HT_DIR_OK 2 /* Any accesible directory */ +#ifndef HTFILE_H +#define HTFILE_H -#define HT_DIR_ENABLE_FILE ".www_browsable" /* If exists, can browse */ +#include "HTProt.h" -extern int HTDirReadme; /* Include readme files? */ - /* Values: */ -#define HT_DIR_README_NONE 0 -#define HT_DIR_README_TOP 1 -#define HT_DIR_README_BOTTOM 2 +#ifdef __cplusplus +extern "C" { +#endif -#define HT_DIR_README_FILE "README" +extern HTProtCallback HTLoadFile; +/* +. + Directory Access +. -/* Convert filenames between local and WWW formats -** ----------------------------------------------- -** Make up a suitable name for saving the node in -** -** E.g. $(HOME)/WWW/news/1234@cernvax.cern.ch -** $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx +You can define the directory access for file URLs by using the following +function. */ -#ifdef __STDC__ -extern char * HTLocalName(const char * name); -#else -extern char * HTLocalName(); -#endif -/* Make a WWW name from a full local path name -** -*/ -extern char * WWW_nameOfFile PARAMS((const char * name)); +typedef enum _HTDirAccess { + HT_DIR_FORBID, /* Altogether forbidden */ + HT_DIR_SELECTIVE, /* Only if "selfile" exists */ + HT_DIR_OK /* Directory reading always OK */ +} HTDirAccess; + +#define DEFAULT_DIR_FILE ".www_browsable" /* If exists, can browse */ +extern HTDirAccess HTFile_dirAccess (void); +extern BOOL HTFile_setDirAccess (HTDirAccess mode); + +/* +. + Readme Files +. -/* Generate the name of a cache file +You can specify the module to look for a README file and to put into a directory +listing. These are the possibilities: */ -extern char * HTCacheFileName PARAMS((CONST char * name)); +typedef enum _HTDirReadme { + HT_DIR_README_NONE, + HT_DIR_README_TOP, + HT_DIR_README_BOTTOM +} HTDirReadme; +#define DEFAULT_README "README" -/* Define the representation for a file suffix -** ------------------------------------------- -** -** On entry, -** suffix includes the "." if that is important (normally, yes!) -** representation is MIME-style -** quality an a priori judgement of the quality of such files -** -** Example: HTSetSuffix(".ps", "application/postscript", 1.0); -** -*/ +extern HTDirReadme HTFile_dirReadme (void); +extern BOOL HTFile_setDirReadme (HTDirReadme mode); -extern void HTSetSuffix PARAMS(( - CONST char * suffix, - CONST char * representation, - float quality)); - +/* +. + Should we do Automatic File Suffix Binding? +. -/* Determine file format from file name -** ------------------------------------ -*/ +By default, libwww uses the file suffix bindings +to figure out the media type, natural language, charset, content encoding, +etc and assign the values to the anchor of the local file. -#ifdef __STDC__ -extern HTFormat HTFileFormat(const char * filename); -#else -extern HTFormat HTFileFormat(); -#endif +However, in some situations, the application can either already have done +this or isn't interested in using the libwww bindings. You can control whether +libwww should do thi or not using the following methods: +*/ +extern BOOL HTFile_doFileSuffixBinding (BOOL mode); +extern BOOL HTFile_fileSuffixBinding (void); -/* Determine file format from file name -** ------------------------------------ +/* +Calculate the required buffer size (in bytes) for directory +entries read from the given directory handle, as per security advisory +from Ben Hutchings. +Return -1 if this this cannot be done. */ -extern float HTFileValue PARAMS((CONST char * filename)); +extern size_t HTFile_dirent_buf_size(DIR * dirp); +/* -/* Determine write access to a file -// -------------------------------- -// -// On exit, -// return value YES if file can be accessed and can be written to. -// -// Isn't there a quicker way? */ -#ifdef __STDC__ -extern BOOL HTEditable(const char * filename); -#else -extern BOOL HTEditable(); +#ifdef __cplusplus +} #endif - -/* Determine a suitable suffix, given the representation -** ----------------------------------------------------- -** -** On entry, -** rep is the atomized MIME style representation -** -** On exit, -** returns a pointer to a suitable suffiz string if one has been -** found, else NULL. -*/ -extern CONST char * HTFileSuffix PARAMS((HTAtom* rep)); - - -/* Open a file descriptor for a document -** ------------------------------------- -** -** On entry, -** addr must point to the fully qualified hypertext reference. -** -** On exit, -** returns <0 Error has occured. -** HT_LOADED Done OK -** -** *pFormat Set to the format of the file, if known. -** (See WWW.h) -** -*/ -/* -extern int HTLoadFile -PARAMS -(( - const char * addr, - HTParentAnchor * anchor, - int diagnostic -)); -*/ -extern HTProtocol HTFTP, HTFile; #endif /* HTFILE_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTFormat.h b/Library/src/HTFormat.h index 7a19f64e..e52513e2 100644 --- a/Library/src/HTFormat.h +++ b/Library/src/HTFormat.h @@ -1,16 +1,72 @@ -/* HTFormat: The format manager in the WWW Library - MANAGE DIFFERENT DOCUMENT FORMATS - - Here we describe the functions of the HTFormat module which handles conversion between - different data representations. (In MIME parlance, a representation is known as a - content-type. In WWW the term "format" is often used as it is shorter). - - This module is implemented by HTFormat.c. This hypertext document is used to generate - the HTFormat.h inlude file. - -Preamble - - */ +/* + + + W3C Sample Code Library libwww Stream Pipe Manager + + +! + The Stream Pipe Manager +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +The Stream Pipe Manager is responsible for setting up the stream pipe from +the Channel Object to the +Request Object when data is arriving, for example +as a response to s HTTP Get request. As data +arrives, we start to parse it and the more we know the more we can build +up our stream pipe. For example, in the case of HTTP, we first have a stream +that can parse the HTTP response line containing "200 OK". Then +we have a MIME parser for handling the MIME headers. +When the MIME headers have been parsed, we know the content type and any +encoding of the MIME body. If we need to decode a chunked encoding then we +set up a chunked decoder, and if we have to parse a HTML object then we set +up a HTML parser. + +The Format Manager is also responsible for keeping track of the +"preferences" of the application and/or user. It is an integral part +of the Web and HTTP, that the client application can express its preferences +as a set of "accept" headers in a HTTP request. This task is highly related +to the task mentioned above as we there use the modules that are registered +and here tell the remote server what we are capable of doing and what we +would prefer. + +Note: The library core does not define any default decoders +or parsers - they are all considered part of the application. The library +comes with a default set of parsers including the ones mentioned above which +can be initiated using the functions in HTInit +module. There are different initialization functions for content type +parsers and content encodings respectively. + + + o + Content Type Converters and Presenters + o + Content Encoders and Decoders + o + Content Charsets + o + Natural Languages + + +The application can assign its preferences in two ways: either locally +to a single request or globally to all requests. The local assignment +can either add to or override the global settings depending +on how they are registered. All local registration is handled by the +Request Object and the global registration is handled +by the Format Manager. + +This module is implemented by HTFormat.c, and it +is a part of the W3C Sample Code +Library. +*/ + #ifndef HTFORMAT_H #define HTFORMAT_H @@ -18,265 +74,702 @@ Preamble #include "HTStream.h" #include "HTAtom.h" #include "HTList.h" +#include "HTAnchor.h" +#include "HTReq.h" -#ifdef SHORT_NAMES -#define HTOutputSource HTOuSour -#define HTOutputBinary HTOuBina -#endif +#ifdef __cplusplus +extern "C" { +#endif /* +. + Converters and Presenters +. + +All content type converters are subclassed from the Generic stream objetc. +That way, we allow the application to do very fast progressive display of +incoming data. In other words, the stream model of the Library provides data +as soon as it arrives from the network, the application does not have to +wait until the whole document has been down loaded before it starts parsing +it. +( + Predefined Content Types +) + +These macros (which used to be constants) define some basic internally referenced +representations. The www/xxx ones are of course not MIME standard. +They are internal representations used in the Library but they can't be exported +to other apps! +*/ + +#define WWW_INTERNAL HTAtom_for("www/*") /* All internal formats */ -The HTFormat type +/* + +WWW_INTERNAL represent all internal formats. This can for example +be used to match using the HTMIMEMatch(...). +*/ + +#define WWW_RAW HTAtom_for("www/void") /* Raw output from Protocol */ - We use the HTAtom object for holding representations. This allows faster manipulation - (comparison and copying) that if we stayed with strings. - - */ -typedef HTAtom * HTFormat; - /* - These macros (which used to be constants) define some basic internally referenced - representations. The www/xxx ones are of course not MIME standard. - - www/source is an output format which leaves the input untouched. It is useful for - diagnostics, and for users who want to see the original, whatever it is. - - */ - /* Internal ones */ -#define WWW_SOURCE HTAtom_for("www/source") /* Whatever it was originally*/ +WWW_RAW is an output format which leaves the input untouched +exactly as it is received by the protocol module. For example, in +the case of FTP, this format returns raw ASCII objects for directory listings; +for HTTP, everything including the header is returned, for Gopher, a raw +ASCII object is returned for a menu etc. +*/ + +#define WWW_SOURCE HTAtom_for("*/*") /* - www/present represents the user's perception of the document. If you convert to - www/present, you present the material to the user. - - */ -#define WWW_PRESENT HTAtom_for("www/present") /* The user's perception */ +WWW_SOURCE is an output format which leaves the input untouched +exactly as it is received by the protocol module IF not a +suitable converter has been registered with a quality factor higher than +1 (for example 2). In this case the SUPER CONVERTER is preferred +for the raw output. This can be used as a filter effect that allows conversion +from, for example raw FTPdirectory listings into HTML but passes a MIME body +untouched. +*/ + +#define WWW_PRESENT HTAtom_for("www/present") /* - The message/rfc822 format means a MIME message or a plain text message with no MIME - header. This is what is returned by an HTTP server. - - */ -#define WWW_MIME HTAtom_for("www/mime") /* A MIME message */ +WWW_PRESENT represents the user's perception of the document. +If you convert to WWW_PRESENT, you present the material to the +user. +*/ + +#define WWW_DEBUG HTAtom_for("www/debug") + /* - www/print is like www/present except it represents a printed copy. - - */ -#define WWW_PRINT HTAtom_for("www/print") /* A printed copy */ +WWW_DEBUG represents the user's perception of debug information, +for example sent as a HTML document in a HTTP redirection message. +*/ + +#define WWW_UNKNOWN HTAtom_for("www/unknown") -#define WWW_PLAINTEXT HTAtom_for("text/plain") -#define WWW_POSTSCRIPT HTAtom_for("application/postscript") -#define WWW_RICHTEXT HTAtom_for("application/rtf") -#define WWW_HTML HTAtom_for("text/html") -#define WWW_BINARY HTAtom_for("application/binary") /* - We must include the following file after defining HTFormat, to which it makes - reference. - - */ -#include "HTAnchor.h" +WWW_UNKNOWN is a really unknown type. It differs from the real +MIME type "application/octet-stream" in that we haven't even tried +to figure out the content type at this point. +*/ + +#define WWW_CACHE HTAtom_for("www/cache") +#define WWW_CACHE_APPEND HTAtom_for("www/cache-append") + +/* + +WWW_CACHE is the internal content-type designated for a persistent +cache module which can store the object to local storage. The cache append +format is special in that we append information to an already existing cache +entry. This can happen if we have issued a If-Range request +and got back a "206 Partial response". + +These are regular MIME types defined. Others can be added! +*/ + +#define WWW_HTML HTAtom_for("text/html") +#define WWW_PLAINTEXT HTAtom_for("text/plain") +#define WWW_FORM HTAtom_for("application/x-www-form-urlencoded") + +#define WWW_MIME HTAtom_for("message/rfc822") +#define WWW_MIME_HEAD HTAtom_for("message/x-rfc822-head") +#define WWW_MIME_FOOT HTAtom_for("message/x-rfc822-foot") +#define WWW_MIME_PART HTAtom_for("message/x-rfc822-partial") +#define WWW_MIME_CONT HTAtom_for("message/x-rfc822-cont") +#define WWW_MIME_UPGRADE HTAtom_for("message/x-rfc822-upgrade") + +#define WWW_MIME_COPYHEADERS HTAtom_for("www/x-rfc822-headers") + +#define WWW_AUDIO HTAtom_for("audio/basic") + +#define WWW_VIDEO HTAtom_for("video/mpeg") + +#define WWW_GIF HTAtom_for("image/gif") +#define WWW_JPEG HTAtom_for("image/jpeg") +#define WWW_TIFF HTAtom_for("image/tiff") +#define WWW_PNG HTAtom_for("image/png") + +#define WWW_BINARY HTAtom_for("application/octet-stream") +#define WWW_POSTSCRIPT HTAtom_for("application/postscript") +#define WWW_RICHTEXT HTAtom_for("application/rtf") + +/* + +We also have some MIME types that come from the various protocols when we +convert from ASCII to HTML. +*/ + +#define WWW_GOPHER_MENU HTAtom_for("text/x-gopher") +#define WWW_CSO_SEARCH HTAtom_for("text/x-cso") + +#define WWW_FTP_LNST HTAtom_for("text/x-ftp-lnst") +#define WWW_FTP_LIST HTAtom_for("text/x-ftp-list") + +#define WWW_NNTP_LIST HTAtom_for("text/x-nntp-list") +#define WWW_NNTP_OVER HTAtom_for("text/x-nntp-over") +#define WWW_NNTP_HEAD HTAtom_for("text/x-nntp-head") + +#define WWW_HTTP HTAtom_for("text/x-http") + +/* + +Finally we have defined a special format for our RULE files as they can be +handled by a special converter. +*/ +#define WWW_RULES HTAtom_for("application/x-www-rules") + +/* +( + The Quality Factor +) + +Characteristic for all preferences is that there is a quality factor associated +with each member. The quality factor is a real number between 0 and 1 with +0 meaning "very bad" and 1 means "perfect". By registering a natural language +or any or other preference in this group together with a quality factor you +can specify "how well the preference is handled" either by the application +or by the user. In the case of the user the quality factor of a natural language +is how well the user understands the language. In my case, the quality factors +for, for example Greek would be close to zero and 1 for Danish (nothing bad +said about Greek!). + +It is a bit different for converters where it is often the application's +ability of handling the data format rather than the user's perception. As +an example it is often faster to use a converter than a presenter as it takes +time to launch the external application and libwww can not use progressive +display mechanisms which is often the case for converters. Therefore, as +an example, if we capable of handling an image in png format inline +but rely on an external viewer for presenting postscript, we might set up +the following list: + +HTConversion_add (converters, "image", "www/present", GifPresenter, +1.0, 0.0, 0.0); +HTPresentation_add (presenters, "application/postscript", "ghostview %s", +NULL, 0.5, 0.0, 0.0);> + +where the gif converter is registered with a quality factor of 1.0 +and the postscript presenter with a quality factor of 0.5.Register +Presenters +( + The Converter Class +) + +A converter is a stream with a special set of parameters and +which is registered as capable of converting from a MIME type to something +else (maybe another MIME-type). A converter is defined to be a function returning +a stream and accepting the following parameters. The content type elements +are atoms for which we have defined a prototype. +*/ + +typedef HTStream * HTConverter (HTRequest * request, + void * param, + HTFormat input_format, + HTFormat output_format, + HTStream * output_stream); + +extern void HTConversion_add (HTList * conversions, + const char * rep_in, + const char * rep_out, + HTConverter * converter, + double quality, + double secs, + double secs_per_byte); + +extern void HTConversion_deleteAll (HTList * list); + +/* +( + The Presenter Class +) + +A presenter is a module (possibly an external program) which +can present a graphic object of a certain MIME type to the user. That is, +presenters are normally used to present objects that the +converters are not able to handle. Data is transferred to the +external program using a special "presenter stream" which for example can +use the local disk to transfer the data from libwww to the external program. + +Libwww provides a default HTSaveAndExecute +stream which you may want to use for this purpose. However, any stream +that is of type HTConverter will do. You can manage the +special presenter stream using the following methods: +*/ + +extern void HTPresentation_setConverter (HTConverter * pconv); +extern HTConverter * HTPresentation_converter (void); + +/* +Both presenters and converters are of the type +HTConverter. +*/ + +extern void HTPresentation_add (HTList * conversions, + const char * representation, + const char * command, + const char * test_command, + double quality, + double secs, + double secs_per_byte); + +extern void HTPresentation_deleteAll (HTList * list); + +/* +( + Basic Converters +) + +We have a small set of basic converters that can be hooked in anywhere. They +don't "convert" anything but are nice to have. +*/ + +extern HTConverter HTThroughLine; +extern HTConverter HTBlackHoleConverter; +extern HTConverter HTSaveConverter; + +/* +. + Content and Transfer Encoders and Decoders +. + +Content codins are transformations applied to an entity object after it was +created in its original form. The Library handles two types of codings: + + + Content Codings + + Content codings values indicate an encoding transformation that has been + applied to a resource. Content cosings are primarily used to allow a document + to be compressed or encrypted without loosing the identity of its underlying + media type. + + Content Transfer Codings + + Content transfer codings values are used to indicate an encoding transformation + that has been, can be, or may be need to be applied to an enity body in order + to ensure safe transport through the network. This differs from a content + coding in that the transfer coding is a property of the message, not the + original message. + + +Both types of encodings use the same registration mechanism in the Library +which we describe below: +( + Encoders and Decoders +) + +Encoders and decoders are subclassed from the +generic stream class. Encoders are capable +of adding a content coding to a data object and decoders can remove +a content coding. +*/ + +typedef HTStream * HTCoder (HTRequest * request, + void * param, + HTEncoding coding, + HTStream * target); + +/* + +The encoding is the name of the encoding mechanism reporesented +as an atom, for example "zip", "chunked", etc. +Encodings are registered in lists and content encodings are separated from +transfer encodings by registering them in different lists. +( + Basic Encoders +) + +We have a small set of basic coders that can be hooked in anywhere. +*/ + +extern HTCoder HTIdentityCoding; + +/* +( + The HTCoding Object +) + +The HTCoding object represents a registered encoding together with +a encoder and a decoder. +*/ + +typedef struct _HTCoding HTCoding; + +/* + +Predefined Coding Types We have a set of pre defined atoms for various types +of content encodings and transfer encodings. "chunked" is not exactly in +the same group as the other encodings such as "binary" but it really doesn't +make any difference as it is just a matter of how the words are chosen. The +first three transfer encodings are actually not encodings - they are just +left overs from brain dead mail systems. +*/ + +#define WWW_CODING_7BIT HTAtom_for("7bit") +#define WWW_CODING_8BIT HTAtom_for("8bit") +#define WWW_CODING_BINARY HTAtom_for("binary") +#define WWW_CODING_IDENTITY HTAtom_for("identity") + +#define WWW_CODING_BASE64 HTAtom_for("base64") +#define WWW_CODING_MACBINHEX HTAtom_for("macbinhex") +#define WWW_CODING_CHUNKED HTAtom_for("chunked") + +#define WWW_CODING_COMPRESS HTAtom_for("compress") +#define WWW_CODING_GZIP HTAtom_for("gzip") +#define WWW_CODING_DEFLATE HTAtom_for("deflate") /* +( + Register Content Coders +) -The HTPresentation and HTConverter types +Some documents are not send in their original data obejct but is encoded +in some way. On the Web this is mostly some kind of compression but other +encodings for example base 64 can be encountered when talking to NNTP servers +etc. Just as for the other preferences, an application can register a supported +encoders or decodes as a list. Encoders and decoders are registered in the +same way with no differentiation whether it is a encoder or a decoder: +*/ - This HTPresentation structure represents a possible conversion algorithm from one - format to annother. It includes a pointer to a conversion routine. The conversion - routine returns a stream to which data should be fed. See also HTStreamStack which - scans the list of registered converters and calls one. See the initialisation module - for a list of conversion routines. - - */ -typedef struct _HTPresentation HTPresentation; +extern BOOL HTCoding_add (HTList * list, + const char * encoding, + HTCoder * encoder, + HTCoder * decoder, + double quality); -typedef HTStream * HTConverter PARAMS(( - HTPresentation * pres, - HTParentAnchor * anchor, - HTStream * sink)); - -struct _HTPresentation { - HTAtom* rep; /* representation name atmoized */ - HTAtom* rep_out; /* resulting representation */ - HTConverter *converter; /* The routine to gen the stream stack */ - char * command; /* MIME-format string */ - float quality; /* Between 0 (bad) and 1 (good) */ - float secs; - float secs_per_byte; -}; - -/* +extern void HTCoding_deleteAll (HTList * list); - The list of presentations is kept by this module. It is also scanned by modules which - want to know the set of formats supported. for example. - - */ -extern HTList * HTPresentations; +extern const char * HTCoding_name (HTCoding * me); + +extern double HTCoding_quality (HTCoding * me); /* +. + Content Charsets +. + +As the Web reaches all parts of the Internet there are more and more documents +written in languages which contains characters not included in the ISO-8859-1 +character set. A consequence of this the set of characters sets is often +tightly connected with the natural language. libwww does not directly support +other character sets but in case an application is capable of handling +alternative sets it can register these as preferred character sets along +with a quality factor just as all the other preferences in this section. +*/ +extern void HTCharset_add (HTList * list, const char * charset, double quality); -HTSetPresentation: Register a system command to present a format +/* +*/ +typedef struct _HTAcceptNode { + HTAtom * atom; + double quality; +} HTAcceptNode; -On entry, +/* +*/ - rep is the MIME - style format name - - command is the MAILCAP - style command template - - quality A degradation faction 0..1 - - maxbytes A limit on the length acceptable as input (0 infinite) - - maxsecs A limit on the time user will wait (0 for infinity) - - */ -extern void HTSetPresentation PARAMS(( - CONST char * representation, - CONST char * command, - float quality, - float secs, - float secs_per_byte -)); +extern void HTCharset_deleteAll (HTList * list); +/* +. + Content Languages +. + +The preferred natural language or languages is in almost all situations dependent +on the individual user and an application should therefore give the user +the opportunity to change the setup. When specifying a natural language +preference, libwww will send this preference along with all HTTP requests. +The remote server will then (it if supports this feature) look for a version +in the language or languages mentioned. If it finds a matching document then +it returns this one, otherwise it uses the best alternative. If no language +is specified the remote server may whatever version it finds. +*/ +extern void HTLanguage_add (HTList * list, const char * lang, double quality); +extern void HTLanguage_deleteAll (HTList * list); /* +. + Global Preferences +. + +There are two places where these preferences can be registered: in a +global list valid for all requests and a local list +valid for a particular request only. These are valid for all requests. +See the Request Manager fro local sets. +( + Global Converters and Presenters +) + +The global list of specific conversions which the format manager +can do in order to fulfill the request. There is also a +local list of conversions which contains +a generic set of possible conversions. +*/ +extern void HTFormat_setConversion (HTList * list); +extern HTList * HTFormat_conversion (void); + +extern void HTFormat_addConversion (const char * input_format, + const char * output_format, + HTConverter * converter, + double quality, + double secs, + double secs_per_byte); -HTSetConversion: Register a converstion routine +/* +( + Global Content Codings +) +*/ +extern void HTFormat_setContentCoding (HTList * list); +extern HTList * HTFormat_contentCoding (void); + +extern BOOL HTFormat_addCoding ( char * encoding, + HTCoder * encoder, + HTCoder * decoder, + double quality); -On entry, +/* - rep_in is the content-type input - - rep_out is the resulting content-type - - converter is the routine to make the stream to do it - - */ +We also define a macro to find out whether a content encoding is really an +encoding or whether it is a unity encoder. +*/ -extern void HTSetConversion PARAMS(( - CONST char * rep_in, - CONST char * rep_out, - HTConverter * converter, - float quality, - float secs, - float secs_per_byte -)); +#define HTFormat_isUnityContent(me) \ + ((me)==NULL || \ + (me)==WWW_CODING_BINARY || (me)==WWW_CODING_IDENTITY || \ + (me)==WWW_CODING_7BIT || (me)==WWW_CODING_8BIT) +/* +( + Global Transfer Codings +) +*/ +extern void HTFormat_setTransferCoding (HTList * list); +extern HTList * HTFormat_transferCoding (void); + +extern BOOL HTFormat_addTransferCoding ( char * encoding, + HTCoder * encoder, + HTCoder * decoder, + double quality); /* -HTStreamStack: Create a stack of streams +We also define a macro to find out whether a transfer encoding is really +an encoding or whether it is just a "dummy" as for example 7bit, 8bit, and +binary. +*/ - This is the routine which actually sets up the conversion. It currently checks only for - direct conversions, but indirect conversions are forseen. It takes a stream into which - the output should be sent in the final format, builds the conversion stack, and returns - a stream into which the data in the input format should be fed. The anchor is passed - because hypertxet objects load information into the anchor object which represents - them. - - */ -extern HTStream * HTStreamStack PARAMS(( - HTFormat format_in, - HTFormat format_out, - HTStream* stream_out, - HTParentAnchor* anchor)); +#define HTFormat_isUnityTransfer(me) \ + ((me)==NULL || \ + (me)==WWW_CODING_BINARY || (me)==WWW_CODING_IDENTITY || \ + (me)==WWW_CODING_7BIT || (me)==WWW_CODING_8BIT) /* +( + Global Content Languages +) +*/ +extern void HTFormat_setLanguage (HTList * list); +extern HTList * HTFormat_language (void); -HTStackValue: Find the cost of a filter stack +/* +( + Global Content Charsets +) +*/ +extern void HTFormat_setCharset (HTList * list); +extern HTList * HTFormat_charset (void); - Must return the cost of the same stack which HTStreamStack would set up. - -On entry, +/* +( + Delete All Global Lists +) - format_in The fomat of the data to be converted - - format_out The format required - - initial_value The intrinsic "value" of the data before conversion on a scale - from 0 to 1 - - length The number of bytes expected in the input format - - */ -extern float HTStackValue PARAMS(( - HTFormat format_in, - HTFormat rep_out, - float initial_value, - long int length)); +This is a convenience function that might make life easier. +*/ +extern void HTFormat_deleteAll (void); -#define NO_VALUE_FOUND -1e20 /* returned if none found */ +/* +. + The Content Type Stream Stack +. + +This is the routine which actually sets up the content type conversion. It +currently checks only for direct conversions, but multi-stage conversions +are forseen. It takes a stream into which the output should be sent in the +final format, builds the conversion stack, and returns a stream into which +the data in the input format should be fed. If guess is true +and input format is www/unknown, try to guess the format by +looking at the first few bytes of the stream. +*/ + +extern HTStream * HTStreamStack (HTFormat rep_in, + HTFormat rep_out, + HTStream * output_stream, + HTRequest * request, + BOOL guess); /* +( + Cost of a Stream Stack +) -HTCopy: Copy a socket to a stream +Must return the cost of the same stack which HTStreamStack would set up. +*/ - This is used by the protocol engines to send data down a stream, typiclly one which has - been generated by HTStreamStack. - - */ -extern void HTCopy PARAMS(( - int file_number, - HTStream* sink)); +extern double HTStackValue (HTList * conversions, + HTFormat format_in, + HTFormat format_out, + double initial_value, + long int length); - /* +. + Content Encoding Stream Stack +. + +When creating a coding stream stack, it is important that we keep the right +order of encoders and decoders. As an example, the HTTP spec specifies that +the list in the Content-Encoding header follows the order in which +the encodings have been applied to the object. Internally, we represent the +content encodings as atoms in a linked +list object. + +The creation of the content coding stack is not based on quality factors +as we don't have the freedom as with content types. When using content codings +we must apply the codings specified or fail. +*/ + +extern HTStream * HTContentCodingStack (HTEncoding coding, + HTStream * target, + HTRequest * request, + void * param, + BOOL encoding); - HTCopyNoCRThis one strips CR characters. It is slower than HTCopy . - - */ +/* -extern void HTCopyNoCR PARAMS(( - int file_number, - HTStream* sink)); +Here you can provide a complete list instead of a single token. The list +has to be filled up in the order the _encodings_ are to be applied +*/ +extern HTStream * HTContentEncodingStack (HTList * encodings, + HTStream * target, + HTRequest * request, + void * param); /* -Clear input buffer and set file number +Here you can provide a complete list instead of a single token. The list +has to be in the order the _encodings_ were applied - that is, the same way +that _encodings_ are to be applied. This is all consistent with the order +of the Content-Encoding header. +*/ - This routine and the one below provide simple character input from sockets. (They are - left over from the older architecure and may not be used very much.) The existence of - a common routine and buffer saves memory space in small implementations. - - */ -extern void HTInitInput PARAMS((int file_number)); +extern HTStream * HTContentDecodingStack (HTList * encodings, + HTStream * target, + HTRequest * request, + void * param); /* +. + Transfer Encoding Stream Stack +. + +When creating a coding stream stack, it is important that we keep the right +order of encoders and decoders. As an example, the HTTP spec specifies that +the list in the Transfer-Encoding header follows the order in which +the encodings have been applied to the object. Internally, we represent the +content encodings as atoms in a linked +list object. + +The creation of the content coding stack is not based on quality factors +as we don't have the freedom as with content types. When using content codings +we must apply the codings specified or fail. +*/ + +extern HTStream * HTTransferCodingStack (HTEncoding coding, + HTStream * target, + HTRequest * request, + void * param, + BOOL encoding); -Get next character from buffer +/* - */ -extern char HTGetChararcter NOPARAMS; +Here you can provide a complete list instead of a single token. The list +has to be filled up in the order the _encodings_ are to be applied +*/ +extern HTStream * HTTransferEncodingStack (HTList * encodings, + HTStream * target, + HTRequest * request, + void * param); /* -HTParseSocket: Parse a socket given its format +Here you can provide a complete list instead of a single token. The list +has to be in the order the _encodings_ were applied - that is, the same way +that _encodings_ are to be applied. This is all consistent with the order +of the Transfer-Encoding header. +*/ - This routine is called by protocol modules to load an object. uses HTStreamStack and - the copy routines above. Returns HT_LOADED if succesful, <0 if not. - - */ -extern int HTParseSocket PARAMS(( - HTFormat format_in, - HTFormat format_out, - HTParentAnchor *anchor, - int file_number, - HTStream* sink)); +extern HTStream * HTTransferDecodingStack (HTList * encodings, + HTStream * target, + HTRequest * request, + void * param); /* +. + Transfer Encoding Stream Stack +. -Epilogue +Creating the transfer content encoding stream stack is not based on quality +factors as we don't have the freedom as with content types. Specify whether +you you want encoding or decoding using the BOOL "encode" flag. +*/ + +extern HTStream * HTContentTransferCodingStack (HTEncoding encoding, + HTStream * target, + HTRequest * request, + void * param, + BOOL encode); + +/* +( + Presentation Object +) + +This object is not to be used - it should have been hidden  +*/ +typedef struct _HTPresentation { + HTFormat rep; /* representation name atomized */ + HTFormat rep_out; /* resulting representation */ + HTConverter *converter; /* The routine to gen the stream stack */ + char * command; /* MIME-format string */ + char * test_command; /* MIME-format string */ + double quality; /* Between 0 (bad) and 1 (good) */ + double secs; + double secs_per_byte; +} HTPresentation; - */ -extern BOOL HTOutputSource; /* Flag: shortcut parser */ +/* +*/ + +#ifdef __cplusplus +} #endif +#endif /* HTFORMAT */ + /* - end */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTGopher.h b/Library/src/HTGopher.h index 44af93bd..426e89ff 100644 --- a/Library/src/HTGopher.h +++ b/Library/src/HTGopher.h @@ -1,25 +1,52 @@ -/* */ +/* + + W3C Sample Code Library libwww GOPHER CLIENT + + + + +!Gopher Access! + +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module also cantains the CSO Name Server access via Gopher. + +This module is implemented by HTGopher.c, and +it is a part of the W3C +Sample Code Library. -/* GOPHER ACCESS HTGopher.h -** ============= -** -** History: -** 8 Jan 92 Adapted from HTTP TBL */ #ifndef HTGOPHER_H #define HTGOPHER_H -#include "HTAccess.h" -#include "HTAnchor.h" +#include "HTProt.h" -/* extern int HTLoadGopher PARAMS((const char *arg, - HTParentAnchor * anAnchor, - int diag)); -*/ -extern HTProtocol HTGopher; +#ifdef __cplusplus +extern "C" { +#endif + +extern HTProtCallback HTLoadGopher; + + +#ifdef __cplusplus +} +#endif + +#endif /* HTGOPHER_H */ -#endif /* HTGOPHER_H */ /* - */ + + +@(#) $Id$ + + +*/ diff --git a/Library/src/HTInit.h b/Library/src/HTInit.h index 07efbbdf..543c4d09 100644 --- a/Library/src/HTInit.h +++ b/Library/src/HTInit.h @@ -1,18 +1,299 @@ -/* */ +/* + + + W3C Sample Code Library libwww Default Initialization + + +! + Default Initialization Methods +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +As mentioned in the Library Architecture, +libwww consists of a small core and a large set of hooks for adding +functionality. By itself, the core it not capable of performing any Web related +tasks like accessing a HTTP server or parsing a HTML document. All this +functionality must be registered by the application. This way, the core of +libwww is kept application independent and can be used as the basic building +block for any kind of Web application. The Library comes with a large set +of default functions, for example for accessing HTTP and FTP servers, parsing +RFC +822 headers etc. This module helps the application programmer setting +up all this functionality, but it is important to note that none of it is +required in order to use the Library. + +This module is implemented by HTInit.c, and it is +a part of the W3C Sample Code +Library. You can also have a look at the other +Initialization modules. +*/ + +#ifndef HTINIT_H +#define HTINIT_H +#include "WWWLib.h" +#include "WWWApp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +. + Default Transport Protocol Modules +. + +Register the default set of transport protocols. +*/ + +#include "WWWTrans.h" + +extern void HTTransportInit (void); + +/* +. + Default Protocol Modules +. + +Set up default bindings between access schemes and the set of protocol modules +in the Library. The preemptive version registers all protocol modules to +use blocking sockets. +*/ + +#include "WWWHTTP.h" +#include "WWWFile.h" +#include "WWWFTP.h" +#include "WWWGophe.h" +#include "WWWTelnt.h" +#include "WWWNews.h" + +#ifdef HT_DIRECT_WAIS +#include "WWWWAIS.h" +#endif + +#ifndef FTP_PORT +#define FTP_PORT 21 +#endif +#ifndef NEWS_PORT +#define NEWS_PORT 119 +#endif +#ifndef GOPHER_PORT +#define GOPHER_PORT 70 +#endif +#ifndef WAIS_PORT +#define WAIS_PORT 666 +#endif +#ifndef HTTP_PORT +#define HTTP_PORT 80 +#endif + +#define HTAccessInit HTProtocolInit + +extern void HTProtocolInit (void); + +extern void HTProtocolPreemptiveInit (void); + +/* +. + Default MIME Parsers +. + +The core doesn't have any built in MIME parsers, but many of the protocols +need them. For instance, many elements of the library rely on the +Content-Length being correctly set. HTMIMEInit() +provides the minimal functionality needed for library reliabilty. +*/ + +#include "WWWMIME.h" +#include "WWWApp.h" + +extern void HTMIMEInit (void); + +/* +. + Default Event Manager +. + +libwww core does not have any default event loop - it has to be added by +the application. However, it does come with an example implementation thta +may be used. This implementation is based on a select system +call using non-blocking and interleaved sockets. +*/ + +#include "WWWApp.h" + +/* +. + Default Media Type Conversions +. + +The Converters are used to convert a media type to another media +type, or to present it on screen. This is a part of the stream stack algorithm. +The Presenters are also used in the stream stack, but are initialized separately. +*/ + +#include "WWWMIME.h" +#include "WWWHTML.h" +#include "WWWStream.h" +#include "WWWDir.h" +#include "WWWCache.h" + +#ifdef HT_EXPAT +#include "WWWXML.h" +#endif + +extern void HTConverterInit (HTList * conversions); + +/* +( + Presenters +) -/* Initialisation module HTInit.h -** -** This module resisters all the plug&play software modules which -** will be used in the program. This is for a browser. -** -** To override this, just copy it and link in your version -** befoe you link with the library. +The Presenters are used to present media types by calling +external programs, for example, a Postscript viewer. This is a part of +the stream stack algorithm. The Converters are also used in the stream +stack, but are initialized separately. The Presenters use the same +include files as the Converters. */ -#include "HTUtils.h" +extern void HTPresenterInit (HTList * conversions); -extern void HTFormatInit NOPARAMS; -extern void HTFileInit NOPARAMS; /* +( + Converters and Presenters +) - */ +This function is only defined in order to preserve backward compatibility. +*/ + +extern void HTFormatInit (HTList * conversions); + +/* +. + Default Transfer Encodings +. + +Transfer encoders and decoders can handle encodings like chunked +etc. +*/ +#include "WWWHTTP.h" + +extern void HTTransferEncoderInit (HTList * encodings); + +/* +. + Default Content Encodings +. + +Content encoders and decoders can handle encodings like deflate +etc. +*/ +#include "WWWZip.h" + +extern void HTContentEncoderInit (HTList * encodings); + +/* +. + Default BEFORE and AFTER Filters +. + +This module provides a set of default BEFORE and AFTER filters +that can be registered by the Net manager to be +called before and after a request. All filters can be registered either to +be called globally (all requests) or locally (pr request basis). +Not done automaticly - may be done by application! +( + BEFORE Filters +) + +The BEFORE filters handle proxies, caches, rule +files etc. The filters are called in the order by which the are registered +*/ +#include "WWWApp.h" + +extern void HTBeforeInit (void); + +/* +( + AFTER Filters +) + +The AFTER filters handle error messages, logging, redirection, +authentication etc. The filters are called in the order by which the are +registered +*/ +extern void HTAfterInit (void); + +/* +( + BEFORE and AFTER Filters +) + +This is just a short cut for registrating both BEFORE and AFTER +at once +*/ +extern void HTNetInit (void); + +/* +. + Default Access Authentication Modules +. + +The Access Manager which is implemented as a +BEFORE and an AFTER filter (automatically registered in +HTNetInit()) does not, by default, know of any access +authentication schemes. As everything else, this must be registered! This +function does the job and should be all you need. +*/ +extern void HTAAInit (void); + +/* +. + Default Message and Dialog Functions +. + +We register a set of alert messages Not done automaticly - may be done by +application! +*/ +#include "WWWApp.h" + +extern void HTAlertInit (void); + +/* +. + Default Icons for Directory Listings +. + +The WWWDir interface contains support for including +references (URLs and ALT text tags) to icons in directory listings. +The icons are selected as a function of the media type and the content encoding +of the file in question. That is - you can set up icons for compressed files, +postscript files etc. There is also a small set of specific icons representing +directories etc. +*/ +#include "WWWFile.h" + +extern void HTIconInit (const char * url_prefix); + +/* +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* HTINIT_H */ + +/* + + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTList.h b/Library/src/HTList.h index fc7c3a6a..c08cbcc7 100644 --- a/Library/src/HTList.h +++ b/Library/src/HTList.h @@ -1,14 +1,38 @@ -/* */ +/* + + + W3C Sample Code Library libwww List Class + + +! + The List Class +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +The list class defines a generic container for storing collections of things +in order. In principle it could be implemented in many ways, but in practice +knowing that it is a linked list is important for speed. -/* List object -** -** The list object is a generic container for storing collections -** of things in order. +This module is implemented by HTList.c, and it is +a part of the W3C Sample Code +Library. */ + #ifndef HTLIST_H #define HTLIST_H -#include "HTUtils.h" /* for BOOL type and PARAMS and ARGS*/ +#include "HTArray.h" + +#ifdef __cplusplus +extern "C" { +#endif typedef struct _HTList HTList; @@ -17,43 +41,156 @@ struct _HTList { HTList * next; }; -#ifdef SHORT_NAMES -#define HTList_new HTLiNew -#define HTList_delete HTLiDele -#define HTList_addObject HTLiAdOb -#define HTList_removeObject HTLiReOb -#define HTList_removeLastObject HTLiReLa -#define HTList_removeFirstObject HTLiReFi -#define HTList_count HTLiCoun -#define HTList_indexOf HTLiInOf -#define HTList_objectAt HTLiObAt -#endif +/* +. + Creation and Deletion Methods +. + +These two functions create and deletes a list +*/ + +extern HTList * HTList_new (void); +extern BOOL HTList_delete (HTList *me); + +/* +. + Add an Element to List +. + +A new list element is added to the beginning of the list so that it is first +element just after the head element. +*/ +extern BOOL HTList_addObject (HTList *me, void *newObject); + +/* + + You can also append an element to the end of +the list (the end is the first entered object) by using the following function: +*/ + +extern BOOL HTList_appendObject (HTList * me, void * newObject); + +/* +The following two functions, contributed by Vic +Bancroft (bancroft@america.net) that do the same operation as above, but return +a pointer to the new HTList element that was added or appended. This allows +one to keep a reference to the end of the list outside of the list itself, +which can be used to speed up certain list operations. +*/ + +extern HTList * HTList_addList (HTList * me, void * newObject); +extern HTList * HTList_appendList (HTList * me, void * newObject); + +/* +. + Remove List Elements +. + +You can delete elements in a list using the following methods. The +first method only removes the first entry that it finds matching the +oldObject whereas the second method removes all +occurances of oldObject. + +*/ + +extern BOOL HTList_removeObject (HTList * me, void * oldObject); +extern BOOL HTList_quickRemoveElement (HTList * me, HTList * last); +extern BOOL HTList_removeObjectAll (HTList * me, void * oldObject); + +extern void * HTList_removeLastObject (HTList * me); +extern void * HTList_removeFirstObject (HTList * me); + +/* +. + Size of a List +. + +Two small function to ask for the size +*/ + +#define HTList_isEmpty(me) (me ? me->next == NULL : YES) +extern int HTList_count (HTList *me); + +/* +. + Reference List Elements By Index +. + +In some situations is is required to use an index in order to refer to a +list element. This is for example the case if an element can be registered +multiple times. +*/ -extern HTList * HTList_new NOPARAMS; -extern void HTList_delete PARAMS((HTList *me)); +extern int HTList_indexOf (HTList * me, void * object); +extern int HTList_indexOfElement (HTList * me, HTList * element); +extern void * HTList_objectAt (HTList * me, int position); +extern HTList * HTList_elementOf (HTList * me, void * object, HTList ** pLast); +#define HTList_objectOf(me) (me ? me->object: NULL) + +/* +. + Find List Elements +. -/* Add object to START of list +This method returns the last element to the list or NULL if list is +empty */ -extern void HTList_addObject PARAMS((HTList *me, void *newObject)); +#define HTList_lastObject(me) \ + ((me) && (me)->next ? (me)->next->object : NULL) -extern BOOL HTList_removeObject PARAMS((HTList *me, void *oldObject)); -extern void * HTList_removeLastObject PARAMS((HTList *me)); -extern void * HTList_removeFirstObject PARAMS((HTList *me)); -#define HTList_isEmpty(me) (me ? me->next == NULL : YES) -extern int HTList_count PARAMS((HTList *me)); -extern int HTList_indexOf PARAMS((HTList *me, void *object)); -#define HTList_lastObject(me) \ - (me && me->next ? me->next->object : NULL) -extern void * HTList_objectAt PARAMS((HTList *me, int position)); +/* + +This method returns the first element to the list or NULL if list +is empty +*/ +extern void * HTList_firstObject (HTList * me); -/* Fast macro to traverse the list. Call it first with copy of list header : - it returns the first object and increments the passed list pointer. - Call it with the same variable until it returns NULL. */ -#define HTList_nextObject(me) \ - (me && (me = me->next) ? me->object : NULL) +/* +. + Traverse list +. + +Fast macro to traverse the list. Call it first with copy of list header: +it returns the first object and increments the passed list pointer. Call +it with the same variable until it returns NULL. +*/ + +#define HTList_nextObject(me) \ + ((me) && ((me) = (me)->next) ? (me)->object : NULL) + +/* +. + Insertion Sort a List +. + +This function sorts a list using the insertion sort mechanism. The comparison +function is passed as a parameter and you can  find the definition of +HTComparer in the HTArray module. +Insertion sort is good method whenever a list is nearly in the correct order +and few items are many positions away from their sorted location. If the +list gets very long then you may wanna use a quicksort instead. +*/ +extern BOOL HTList_insertionSort(HTList * list, HTComparer * comp); + +/* +. + Free list +. +*/ + +#define HTList_free(x) HT_FREE(x) + +#ifdef __cplusplus +} +#endif #endif /* HTLIST_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTMIME.h b/Library/src/HTMIME.h index ab92592c..3a2d214d 100644 --- a/Library/src/HTMIME.h +++ b/Library/src/HTMIME.h @@ -1,29 +1,171 @@ -/* */ +/* + + W3C Sample Code Library libwww MIME Parsers + + +! + Libwww MIME Parsers +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +The MIME parser stream presents a MIME document with a header and possibly +a footer. It recursively invokes the format manager to handle embedded formats +like MIME multipart. As well as stripping off and parsing the headers, the +MIME parser has to parse any weird MIME encodings it may meet within the +body parts of messages, and must deal with multipart +messages (see HTBound.h). -/* MIME Parser HTMIME.h -** ----------- -** -** The MIME parser stream presents a MIME document. -** -** +This module is implemented to the level necessary for operation with WWW, +but is not currently complete for any arbitrary MIME message. + +This module is implemented by HTMIME.c, and it is +a part of the W3C Sample Code +Library. */ #ifndef HTMIME_H #define HTMIME_H #include "HTStream.h" -#include "HTAnchor.h" +#include "HTFormat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +. + How to Deal with Unknown Data +. + +When the MIME parser can't find a target stream, for example because the +media type is unknown, or it has a content encoding or transfer encoding +that it doesn't know about then it has to get rid of the data in some other +fashion, for example by dumping it to local disk (but it could also be dumping +it to a black hole). The following two functions allow you to set and get +the stream to use in this situation. By default, libwww provides an +implementation of a save stream as HTSaveLocally +which you may want to use - this is for example used by the +current profiles. +*/ + +extern void HTMIME_setSaveStream (HTConverter * save_stream); +extern HTConverter * HTMIME_saveStream (void); + +/* +. + MIME Parse Stream +. + +This stream parses a complete MIME message and if a media type header is +found then the stream stack is called to create the nest stream instance +in the stream pipe. Any piece of the MIME body is pumped right through the +stream. +*/ + +extern HTConverter HTMIMEConvert; + +/* +. + MIME Header ONLY Parse Stream +. + +This stream parses a complete MIME header and then returnes +HT_LOADED. It does not set up any streams and resting data stays +in the buffer. This can be used if you only want to parse the headers before +you decide what to do next. This is for example the case with HTTP HEAD requests. +*/ + +extern HTConverter HTMIMEHeader; -extern HTStream * HTMIMEConvert PARAMS((HTPresentation * pres, - HTParentAnchor * anchor, - HTStream * sink)); +/* +. + MIME Footer ONLY Parse Stream +. + +Parse only a footer, for example after a chunked encoding. +*/ + +extern HTConverter HTMIMEFooter; + +/* +. + HTTP 100 Continue Parse Stream +. + +The 100 continue status codes can come at any time - we take them and put +the data down a temporary stream. When the 100 continue message has been +parsed, the stream returns HT_CONTINUE +*/ + +extern HTConverter HTMIMEContinue; + +/* +. + HTTP 101 Switching Protocol Parse Stream +. + +The 101 Switching Protocol status code indicates that the rest of the stream +is using another format, protocol, what ever. The result is the same - we +are done parsing here and must leave the rest to the next stream which hopefully +knows more about how to parse the rest of the stream. The stream stack is +called to look for a stream registered for handling +WWW_MIME_UPGRADE. This steam should +return HT_LOADED when it is done, HT_ERROR if an +error occurred and HT_OK as long as it just reads more data. +*/ + +extern HTConverter HTMIMEUpgrade; +/* +. + HTTP 206 Partial Data MIME Parse Stream +. + +In case we sent a Range conditional GET we may get back a 206 Partial +Response. This response must be appended to the already existing cache entry +before presented to the user. That is, first we load the +cached object and pump it down the pipe and then +the new data follows. Only the latter part gets appended to the cache, of +course. +*/ + +extern HTConverter HTMIMEPartial; + +/* +. + HTMIME_anchor2response +. + +Copies the anchor HTTP headers into a response object by means +of the generic _dispatchParsers function. Written so that we can +copy the HTTP headers stored in the cache to the response object. +*/ +#ifndef NO_CACHE +extern HTConverter HTCacheCopyHeaders; #endif +/* +*/ +#ifdef __cplusplus +} +#endif +#endif /* HTMIME_H */ /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTML.h b/Library/src/HTML.h index 7d6db93d..b561c405 100644 --- a/Library/src/HTML.h +++ b/Library/src/HTML.h @@ -1,73 +1,98 @@ -/* */ +/* + + W3C Sample Code Library libwww HTML Parser With Text Object Converter + + +! + Simple HTML Parser With Text Object Converter +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This interprets the HTML +semantics passed to it by the SGML parser. It then +creates a HText object which the application can +use to render an HTML object as text comes in over the wire. The +stylesheet manager can be used to ensure that +the rendering is done according to whatever style information is present. -/* The HTML to rtf object converter HTML.h -** -------------------------------- +This module is implemented by HTML.c, and it is a part +of the W3C Sample Code Library. */ #ifndef HTML_H #define HTML_H -#include "HTUtils.h" -#include "HTAnchor.h" -#include "HTMLDTD.h" +#include "HTFormat.h" +#include "HTMLPDTD.h" +#ifdef __cplusplus +extern "C" { +#endif -extern CONST HTStructuredClass HTMLPresentation; +/* +. + Converters +. -/* HTConverter to present HTML +These are the converters implemented in this module. The first converts from +HTML to presentation or plain text. */ -PUBLIC HTStream* HTMLToPlain PARAMS(( - HTPresentation * pres, - HTParentAnchor * anchor, - HTStream * sink)); - -PUBLIC HTStream* HTMLToC PARAMS(( - HTPresentation * pres, - HTParentAnchor * anchor, - HTStream * sink)); - -PUBLIC HTStream* HTMLPresent PARAMS(( - HTPresentation * pres, - HTParentAnchor * anchor, - HTStream * sink)); - -extern HTStructured* HTML_new PARAMS(( - HTParentAnchor * anchor, - HTFormat format_out, - HTStream * target)); - -/* Names for selected internal representations: + +extern HTConverter HTMLToPlain; + +/* + +The next converts from HTML to a simple C like representation. It puts everything +not in PRE within C style comments. This is the way that the line mode browser +is used to convert the libwww HTML files to C style .h files */ + +extern HTConverter HTMLToC; + +/* + +This one converts the HTML stream to a rendered object using the +HText interface. +*/ + +extern HTConverter HTMLPresent; + +/* +. + Selecting Internal Character Set Representation +. + +Only ISO_LATIN1 is currently supported. +*/ + typedef enum _HTMLCharacterSet { - HTML_ISO_LATIN1, - HTML_NEXT_CHARS, - HTML_PC_CP950 + HTML_ISO_LATIN1, + HTML_NEXT_CHARS, + HTML_PC_CP950 } HTMLCharacterSet; -extern void HTMLUseCharacterSet PARAMS((HTMLCharacterSet i)); - -/* Record error message as a hypertext object -** ------------------------------------------ -** -** The error message should be marked as an error so that -** it can be reloaded later. -** This implementation just throws up an error message -** and leaves the document unloaded. -** -** On entry, -** sink is a stream to the output device if any -** number is the HTTP error number -** message is the human readable message. -** On exit, -** a retrun code like HT_LOADED if object exists else < 0 -*/ +extern BOOL HTMLUseCharacterSet (HTMLCharacterSet charset); -PUBLIC int HTLoadError PARAMS(( - HTStream * sink, - int number, - CONST char * message)); +/* +*/ +#ifdef __cplusplus +} #endif + +#endif /* end HTML_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTMLGen.h b/Library/src/HTMLGen.h index 02475f4c..ff283354 100644 --- a/Library/src/HTMLGen.h +++ b/Library/src/HTMLGen.h @@ -1,29 +1,69 @@ -/* */ +/* + + W3C Sample Code Library libwww HTML GENERATOR + + + + +!HTML generator! + +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module converts structed stream into stream. That is, given a +stream to write to, it will give you a structured stream to. + +This module is implemented by HTMLGen.c, and +it is a part of the W3C +Sample Code Library. -/* HTML generator */ #ifndef HTMLGEN_H #define HTMLGEN_H -#include "HTML.h" -#include "HTStream.h" +#include "HTStruct.h" +#include "HTFormat.h" -/* Subclass: -*/ -/* extern CONST HTStructuredClass HTMLGeneration; */ +#ifdef __cplusplus +extern "C" { +#endif + +/* + +The HTML generator stream is almost a converter stream but it returns +a structured stream instead of a generic stream. The difference is +that a structured stream has methods for starting and ending mark up +elements and for HTML/SGML entities. -/* Special Creation: */ -extern HTStructured * HTMLGenerator PARAMS((HTStream * output)); -extern HTStream * HTPlainToHTML PARAMS(( - HTPresentation * pres, - HTParentAnchor * anchor, - HTStream * sink)); +extern HTStructured* HTMLGenerator (HTRequest * request, + void * param, + HTFormat input_format, + HTFormat output_format, + HTStream * output_stream); + +extern HTConverter HTPlainToHTML; +#ifdef __cplusplus +} #endif + +#endif /* HTMLGEN_H */ + /* - */ + + +@(#) $Id$ + + +*/ diff --git a/Library/src/HTNews.h b/Library/src/HTNews.h index 43fd439a..ff737eaa 100644 --- a/Library/src/HTNews.h +++ b/Library/src/HTNews.h @@ -1,30 +1,77 @@ -/* Network News Transfer protocol module for the WWW library - HTNEWS - - */ -/* History: -** 26 Sep 90 Written TBL in Objective-C -** 29 Nov 91 Downgraded to C, for portable implementation. +/* + + + W3C Sample Code Library libwww NNTP State Machine + + +! + NNTP State Machine +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This is the News/NNTP client module that handles all communication with +News/NNTP-servers. + +This module is implemented by HTNews.c, and it is +a part of the W3C Sample Code +Library. */ #ifndef HTNEWS_H #define HTNEWS_H +#include "HTProt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* -#include "HTAccess.h" -#include "HTAnchor.h" -/* extern int HTLoadNews PARAMS((const char *arg, - HTParentAnchor * anAnchor, - int diag)); +We define the max NNTP line as rather long as the result coming from a +XOVER command needs it. If the line is longer then it is chopped, +but we will almost have received the information we're looking for. */ -extern HTProtocol HTNews; -extern void HTSetNewsHost PARAMS((CONST char *value)); -extern CONST char * HTGetNewsHost NOPARAMS; -extern char * HTNewsHost; +#ifndef NEWS_PORT +#define NEWS_PORT 119 /* See rfc977 */ +#endif -#endif /* HTNEWS_H */ +#define MAX_NEWS_LINE 4096 + +extern HTProtCallback HTLoadNews; + +/* +( + Setting Number of Articles to Show +) + +You can set the number of news articles to be shown at a time. If you set +the number to none (0) then all articles are shown +at once. This is also the default behavior. +*/ +extern BOOL HTNews_setMaxArticles (int new_max); +extern int HTNews_maxArticles (void); + +/* +*/ +#ifdef __cplusplus +} +#endif + +#endif /* HTNEWS_H */ /* - tbl */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTParse.h b/Library/src/HTParse.h index 101c5edb..d085cdcc 100644 --- a/Library/src/HTParse.h +++ b/Library/src/HTParse.h @@ -1,128 +1,213 @@ -/* HTParse: URL parsing in the WWW Library - HTPARSE - - This module of the WWW library contains code to parse URLs and various related things. - - */ +/* + + + W3C Sample Code Library libwww URI Management + + +! + URI Management +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module contains code to parse URIs and various related things such as: + + o + Parse a URI for tokens + o + Canonicalization of URIs + o + Search a URI for illegal characters in order to prevent + security holes + + +This module is implemented by HTParse.c, and it is +a part of the W3C Sample Code +Library. +*/ + #ifndef HTPARSE_H #define HTPARSE_H -#include "HTUtils.h" + +#include "HTEscape.h" + +#ifdef __cplusplus +extern "C" { +#endif /* +. + Parsing URIs +. + +These functions can be used to get information in a URI. +( + Parse a URI relative to another URI +) + +This returns those parts of a name which are given (and requested) substituting +bits from the related name where necessary. The aName argument +is the (possibly relative) URI to be parsed, the relatedName +is the URI which the aName is to be parsed relative to. Passing +an empty string means that the aName is an absolute URI. The +following are flag bits which may be OR'ed together to form a number to give +the 'wanted' argument to HTParse. As an example we have the URL: +"/TheProject.html#news" +*/ - The following are flag bits which may be ORed together to form a number to give the - 'wanted' argument to HTParse. - - */ -#define PARSE_ACCESS 16 -#define PARSE_HOST 8 -#define PARSE_PATH 4 -#define PARSE_ANCHOR 2 -#define PARSE_PUNCTUATION 1 -#define PARSE_ALL 31 +#define PARSE_ACCESS 16 /* Access scheme, e.g. "HTTP" */ +#define PARSE_HOST 8 /* Host name, e.g. "www.w3.org" */ +#define PARSE_PATH 4 /* URL Path, e.g. "pub/WWW/TheProject.html" */ +#define PARSE_VIEW 2 /* Fragment identifier, e.g. "news" */ +#define PARSE_FRAGMENT PARSE_VIEW +#define PARSE_ANCHOR PARSE_VIEW -/* +#define PARSE_PUNCTUATION 1 /* Include delimiters, e.g, "/" and ":" */ +#define PARSE_ALL 31 -HTParse: Parse a Name relative to another name +/* - This returns those parts of a name which are given (and requested) substituting bits - from the related name where necessary. - - ON ENTRY - - aName A filename given - - relatedName A name relative to which aName is to be parsed - - wanted A mask for the bits which are wanted. - - ON EXIT, - - returns A pointer to a malloc'd string which MUST BE FREED - - */ +where the format of a URI is as follows: "ACCESS :// HOST / PATH # +ANCHOR" -extern char * HTParse PARAMS((const char * aName, const char * relatedName, int wanted)); +PUNCTUATION means any delimiter like '/', ':', '#' between the +tokens above. The string returned by the function must be freed by the caller. +*/ +extern char * HTParse (const char * aName, const char * relatedName, + int wanted); /* +( + Create a Relative (Partial) URI +) -HTStrip: Strip white space off a string +This function creates and returns a string which gives an expression of one +address as related to another. Where there is no relation, an absolute address +is retured. - ON EXIT - Return value points to first non-white character, or to 0 if none. - - All trailing white space is OVERWRITTEN with zero. - - */ -#ifdef __STDC__ -extern char * HTStrip(char * s); -#else -extern char * HTStrip(); -#endif + On entry, + + Both names must be absolute, fully qualified names of nodes (no anchor bits) + + On exit, + + The return result points to a newly allocated name which, if parsed by HTParse + relative to relatedName, will yield aName. The caller is responsible for + freeing the resulting name later. + +*/ + +extern char * HTRelative (const char * aName, const char *relatedName); /* +. + Is a URL Relative or Absolute? +. -HTSimplify: Simplify a filename +Search the URL and determine whether it is a relative or absolute URL. We +check to see if there is a ":" before any "/", "?", and "#". If this is the +case then we say it is absolute. Otherwise we say it is relative. +*/ + +extern BOOL HTURL_isAbsolute (const char * url); - A URL is allowed to contain the seqeunce xxx/../ which may be replaced by "" , and the - seqeunce "/./" which may be replaced by "/". Simplification helps us recognize - duplicate filenames. It doesn't deal with soft links, though. The new (shorter) - filename overwrites the old. - - */ /* -** Thus, /etc/junk/../fred becomes /etc/fred -** /etc/junk/./fred becomes /etc/junk/fred +. + URL Canonicalization +. + +Canonicalization of URIs is a difficult job, but it saves a lot of down loads +and double entries in the cache if we do a good job. A URI is allowed to +contain the seqeunce xxx/../ which may be replaced by "" , and the seqeunce +"/./" which may be replaced by "/". Simplification helps us recognize duplicate +URIs. Thus, the following transformations are done: + + o + /etc/junk/../fred becomes /etc/fred + o + /etc/junk/./fred becomes /etc/junk/fred + + +but we should NOT change + + o + http://fred.xxx.edu/../.. or + o + ../../albert.html + + +In the same manner, the following prefixed are preserved: + + o + ./ + o + // + + +In order to avoid empty URIs the following URIs become: + + o + /fred/.. becomes /fred/.. + o + /fred/././.. becomes /fred/.. + o + /fred/.././junk/.././ becomes /fred/.. + + +If more than one set of `://' is found (several proxies in cascade) then +only the part after the last `://' is simplified. */ -#ifdef __STDC__ -extern void HTSimplify(char * filename); -#else -extern void HTSimplify(); -#endif + +extern char *HTSimplify (char **filename); /* +. + Prevent Security Holes +. -HTRelative: Make Relative Name +In many telnet like protocols, it can be very dangerous to allow a full ASCII +character set to be in a URI. Therefore we have to strip them out. +HTCleanTelnetString() makes sure that the given string doesn't +contain characters that could cause security holes, such as newlines in ftp, +gopher, news or telnet URLs; more specifically: allows everything between +hexadesimal ASCII 20-7E, and also A0-FE, inclusive. - This function creates and returns a string which gives an expression of one address as - related to another. Where there is no relation, an absolute address is retured. - - ON ENTRY, - Both names must be absolute, fully qualified names of nodes (no anchor bits) - - ON EXIT, + str - The return result points to a newly allocated name which, if parsed by HTParse relative - to relatedName, will yield aName. The caller is responsible for freeing the resulting - name later. - - */ -#ifdef __STDC__ -extern char * HTRelative(const char * aName, const char *relatedName); -#else -extern char * HTRelative(); -#endif - -/* + the string that is *modified* if necessary. The string will be truncated + at the first illegal character that is encountered. + + returns + + YES, if the string was modified. NO, otherwise. -HTUnEscape: Decode %xx escaped characters +*/ - This function takes a pointer to a string in which character smay have been encoded in - %xy form, where xy is the acsii hex code for character 16x+y. The string is converted - in place, as it will never grow. - - */ -extern char * HTUnEscape PARAMS(( char * str)); +extern BOOL HTCleanTelnetString (char * str); +/* +*/ +#ifdef __cplusplus +} #endif - +#endif /* HTPARSE_H */ /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTPlain.h b/Library/src/HTPlain.h index 81e8d291..ef530eb6 100644 --- a/Library/src/HTPlain.h +++ b/Library/src/HTPlain.h @@ -1,24 +1,49 @@ -/* */ +/* + + W3C Sample Code Library libwww PLAIN TEXT STREAM + + + + +!Plain text object! + +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module is implemented by HTPlain.c, and +it is a part of the W3C +Sample Code Library. -/* Plain text object HTPlain.h -** ----------------- -** -** */ #ifndef HTPLAIN_H #define HTPLAIN_H -#include "HTStream.h" -#include "HTAnchor.h" +#include "HTFormat.h" -extern HTStream* HTPlainPresent PARAMS(( - HTPresentation * pres, - HTParentAnchor * anchor, - HTStream * sink)); +#ifdef __cplusplus +extern "C" { +#endif +extern HTConverter HTPlainPresent; +#ifdef __cplusplus +} #endif + +#endif /* HTPLAIN_H */ + /* - */ + + +@(#) $Id$ + + +*/ diff --git a/Library/src/HTRules.h b/Library/src/HTRules.h index 7232a96e..a72f9046 100644 --- a/Library/src/HTRules.h +++ b/Library/src/HTRules.h @@ -1,96 +1,157 @@ -/* */ +/* + + W3C Sample Code Library libwww Rule File Configuration manager + + +! + Rule File Configuration Manager +! +*/ -/* Configuration manager for Hypertext Daemon HTRules.h -** ========================================== -** +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. */ -/* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */ +/* +The W3C Library provides this module for handling configuration files (a.k.a. +rule files). Rule files can be used to initialize as much as the application +desires including setting up new protocol modules etc. Also the rules file +do not have to be a fil - it can be a database or any other way of storage +information. This implementation is not used by the Library at all and is +part of the Application interface. + +This module is implemented by HTRules.c, and it is +a part of the W3C Sample Code +Library. +*/ #ifndef HTRULE_H #define HTRULE_H -#include "HTUtils.h" +#include "HTList.h" +#include "HTReq.h" +#include "HTFormat.h" -typedef enum _HTRuleOp {HT_Invalid, HT_Map, HT_Pass, HT_Fail} HTRuleOp; +#ifdef __cplusplus +extern "C" { +#endif -/* Add rule to the list HTAddRule() -** -------------------- -** -** On entry, -** pattern points to 0-terminated string containing a single "*" -** equiv points to the equivalent string with * for the -** place where the text matched by * goes. -** On exit, -** returns 0 if success, -1 if error. +/* +. + Parse a Rule File +. + +Parsing a whole rule file is done using a converter stream. This means +that a rule file can come from anywhere, even accross the network. We +have defined a special content type for rule files called +WWW_RULES in HTFormat and +made a file suffix binding for all files ending in +".conf" in the default +initialization of the file suffix bindings +module. + +The rule file parser comes in two variants: one that asks the user and +one that doesn't. Needless to say that you have to be carefull with +the latter one. You can also define HT_AUTOMATIC_RULES +when compiling libwww to determine +whether it is OK to parse a rule file without asking the user. */ -/* Note that if BYTE_ADDRESSING is set, the three blocks required -** are allocated and deallocated as one. This will save time and -** storage, when malloc's allocation units are large. + +extern HTConverter HTRules, HTRules_parseAutomatically; + +/* +. + Parse a single line from a Rule File +. + +This routine may be used for loading configuration information from sources +other than the rule file, for example INI files for X resources. +config is a string in the syntax of a rule file line. */ -extern int HTAddRule PARAMS((HTRuleOp op, const char * pattern, const char * equiv)); - - -/* Clear all rules HTClearRules() -** --------------- -** -** On exit, -** There are no rules -** returns 0 if success, -1 if error. -** -** See also -** HTAddRule() + +extern BOOL HTRule_parseLine (HTList * list, const char * config); + +/* +. + Add a Rule to the List +. + +This function adds a rule to the list of rules. The pattern +is a 0-terminated string containing a single "*". equiv points +to the equivalent string with * for the place where the text matched by * +goes. */ -#ifdef __STDC__ -extern int HTClearRules(void); -#else -extern int HTClearRules(); -#endif +typedef struct _HTRule HTRule; + +typedef enum _HTRuleOp { + HT_Invalid, + HT_Map, + HT_Pass, + HT_Fail, + HT_DefProt, + HT_Protect, + HT_Exec, + HT_Redirect, + HT_UseProxy +} HTRuleOp; -/* Translate by rules HTTranslate() -** ------------------ -** -** The most recently defined rules are applied first. -** -** On entry, -** required points to a string whose equivalent value is neeed -** On exit, -** returns the address of the equivalent string allocated from -** the heap which the CALLER MUST FREE. If no translation -** occured, then it is a copy of the original. +extern BOOL HTRule_add (HTList * list, HTRuleOp op, + const char * pattern, const char * replace); + +/* +. + Delete all Registered Rules +. + +This function clears all rules registered */ -#ifdef __STDC__ -extern char * HTTranslate(const char * required); -#else -extern char * HTTranslate(); -#endif +extern BOOL HTRule_deleteAll (HTList *list); -/* Load the rules from a file HtLoadRules() -** -------------------------- -** -** On entry, -** Rules can be in any state -** On exit, -** Any existing rules will have been kept. -** Any new rules will have been loaded on top, so as to be tried first. -** Returns 0 if no error. -** -** Bugs: -** The strings may not contain spaces. +/* +. + Global Rules +. + +Rules are handled as list as everything else that has to do with preferences. +We provide two functions for getting and setting the global rules: */ -#ifdef __STDC__ -extern int HTLoadRules(const char * filename); -#else -extern int HTLoadRules(); -#endif +extern HTList * HTRule_global(void); +extern BOOL HTRule_setGlobal (HTList * list); +extern BOOL HTRule_addGlobal (HTRuleOp op, const char * pattern, const char * replace); + +/* +. + Translate by rules +. + +This function walks through the list of rules and translates the reference +when matches are found. The list is traversed in order starting from the +head of the list. It returns the address of the equivalent string allocated +from the heap which the CALLER MUST FREE. If no translation occured, then +it is a copy of the original. +*/ +extern char * HTRule_translate (HTList * list, const char * token, + BOOL ignore_case); -#endif /* HTUtils.h */ +/* +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* HTRULE_H */ /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTString.h b/Library/src/HTString.h index aa7025fc..c85f3006 100644 --- a/Library/src/HTString.h +++ b/Library/src/HTString.h @@ -1,28 +1,153 @@ -/* */ +/* + + + W3C Sample Code Library libwww Generic String Management -/* Case-independent string comparison HTString.h -** and allocations with copies + +! + Generic String Management +! */ -#ifndef HTSTRING_H -#define HTSTRING_H -#include "HTUtils.h" +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ -extern int WWW_TraceFlag; /* Global flag for all W3 trace */ +/* -extern CONST char * HTLibraryVersion; /* String for help screen etc */ +These functions provide functionality for case-independent string comparison +and allocations with copies etc. -extern int strcasecomp PARAMS((CONST char *a, CONST char *b)); -extern int strncasecomp PARAMS((CONST char *a, CONST char *b, int n)); +This module is implemented by HTString.c, and it +is a part of the W3C +Sample Code Library. +*/ + +#ifndef HTSTRING_H +#define HTSTRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* +. + Dynamic String Manipulation +. -extern char * HTSACopy PARAMS ((char **dest, CONST char *src)); -extern char * HTSACat PARAMS ((char **dest, CONST char *src)); +These two functions are dynamic versions of strcpy and +strcat. They use malloc for allocating space for +the string. If StrAllocCopy is called with a non-NULL dest, +then this is freed before the new value is assigned so that only the +last string created has to be freed by the user. If +StrAllocCat is called with a NULL pointer as destination then +it is equivalent to StrAllocCopy. +*/ -/* Enable the old macro-like calling methods */ #define StrAllocCopy(dest, src) HTSACopy (&(dest), src) #define StrAllocCat(dest, src) HTSACat (&(dest), src) +extern char * HTSACopy (char **dest, const char *src); +extern char * HTSACat (char **dest, const char *src); + +/* + +The next two functions take a variable number of strings and cats them together +using dynamic memory. This is basically like a simple form for sprintf where +the only argument is char *. One day we should turn this into +a real dynamic sprintf(). +*/ + +extern char * StrAllocMCopy (char ** dest, ...); +extern char * StrAllocMCat (char ** dest, ...); + +/* + +The last argument MUST be NULL as we otherwise don't know when the argument +list stops. +. + Case-insensitive String Comparison +. + +The usual routines (comp instead of cmp) had some problem. +*/ + +extern int strcasecomp (const char *a, const char *b); +extern int strncasecomp (const char *a, const char *b, int n); + +/* +. + Tail String Comparison +. + +Like strcmp, but match the tail of s2 (used for cookie domain comparison) +*/ + +extern int tailcomp(const char * s1, const char * s2); +extern int tailcasecomp(const char * s1, const char * s2); + +/* +. + String Comparison with Wild Card Match +. + +String comparison function for file names with one wildcard * in the template. +Arguments are: + + + tmpl + + is a template string to match the name against. agaist, may contain a single + wildcard character * which matches zero or more arbitrary characters. + + name + + is the name to be matched agaist the template. + + +Returns empty string ("") if perfect match, pointer to part matched by wildcard +if any, or NULL if no match. This is basically the same as YES if match, +else NO. +*/ + +extern char * HTStrMatch (const char * tmpl, const char * name); +extern char * HTStrCaseMatch (const char * tmpl, const char * name); + +/* +. + Case-insensitive strstr +. + +This works like strstr() but is not case-sensitive. +*/ + +extern char * HTStrCaseStr (char * s1, char * s2); + +/* +. + Strip white space off a string +. + +Return value points to first non-white character, or to '/0' if none. All +trailing white space is OVERWRITTEN with zero. +*/ + +extern char * HTStrip (char * s); + +/* +*/ + +#ifdef __cplusplus +} #endif + +#endif /* !HTSTRING_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTStyle.h b/Library/src/HTStyle.h index 303bcf17..0d1fadbf 100644 --- a/Library/src/HTStyle.h +++ b/Library/src/HTStyle.h @@ -1,161 +1,101 @@ -/* */ - -/* Style Definition for Hypertext HTStyle.h -** ============================== -** -** Styles allow the translation between a logical property of a piece of -** text and its physical representation. -** -** A StyleSheet is a collection of styles, defining the -** translation necessary to represent a document. -** It is a linked list of styles. -*/ -#ifndef HTStyle_H -#define HTStyle_H - -#include "HTUtils.h" -#include "HTAnchor.h" - -/* #include "HTFont.h" bad dependency */ -typedef long int HTFont; /* Dummy definition instead */ - -#ifdef SHORT_NAMES -#define HTStyleNew HTStNew -#define HTStyleFree HTStFree -#define HTStyleRead HTStRead -#define HTStyleWrite HTStWrite -#define HTStyleSheetNew HTStShNe -#define HTStyleSheetFree HTStShFr -#define HTStyleNamed HTStName -#define HTStyleForParagraph HTStFoPa -#define HTStyleMatching HTStMatc -#define HTStyleForRun HTStFoRu -#define HTStyleSheetAddStyle HTStShAd -#define HTStyleSheetRemoveStyle HTStShRm -#define HTStyleSheetRead HTStShRe -#define HTStyleSheetWrite HTStShWr -#endif - -#ifdef NeXT_suppressed -#include -typedef NXCoord HTCoord; -#define HTParagraphStyle NXTextStyle -#define HTCoord NXCoord -typedef struct _color { - float grey; - int RGBColor; -} HTColor; -#else +/* -typedef float HTCoord; + W3C Sample Code Library libwww Stylesheet Manager -typedef struct _HTParagraphStyle { - HTCoord left_indent; /* @@@@ junk! etc etc*/ -} HTParagraphStyle; -typedef int HTColor; /* Sorry about the US spelling! */ +! + Stylesheet Manager +! +*/ -#endif +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ +/* +Styles allow the translation between a logical property of a piece of text +and its physical representation. A StyleSheet is a collection of styles, +defining the translation necessary to represent a document. It is a linked +list of styles. -#define STYLE_NAME_LENGTH 80 /* @@@@@@@@@@@ */ - -typedef struct { - short kind; /* only NX_LEFTTAB implemented*/ - HTCoord position; /* x coordinate for stop */ -} HTTabStop; +A stylesheet is a collection of styles - these styles can either come from +over the net or they can be provided by the application as needed. +The manager doesn't contain any styles - it only provides a mechanism for +registering styles, looking them up and deleting them. That is, it doesn't +have any idea of what a style actually looks like - as this is highly application +dependent, it is not a good idea to provide this as common library code. -/* The Style Structure -** ------------------- +This module is implemented by HTStyle.c, and it is +a part of the W3C Sample Code +Library. */ -typedef struct _HTStyle { +#ifndef HTSTYLE_H +#define HTSTYLE_H -/* Style management information -*/ - struct _HTStyle *next; /* Link for putting into stylesheet */ - char * name; /* Style name */ - char * SGMLTag; /* Tag name to start */ +#ifdef __cplusplus +extern "C" { +#endif +/* +. + Creating and Deleting a StyleSheet +. -/* Character attributes (a la NXRun) +A Stylesheet is a container containing multiple individual styles. You must +therefore first create a stylesheet before you can create individual styles. */ - HTFont font; /* Font id */ - HTCoord fontSize; /* The size of font, not independent */ - HTColor color; /* text gray of current run */ - int superscript; /* superscript (-sub) in points */ - HTAnchor *anchor; /* Anchor id if any, else zero */ +typedef struct _HTStyleSheet HTStyleSheet; -/* Paragraph Attribtes (a la NXTextStyle) -*/ - HTCoord indent1st; /* how far first line in paragraph is - * indented */ - HTCoord leftIndent; /* how far second line is indented */ - HTCoord rightIndent; /* (Missing from NeXT version */ - short alignment; /* quad justification */ - HTCoord lineHt; /* line height */ - HTCoord descentLine; /* descender bottom from baseline */ - HTTabStop *tabs; /* array of tab stops, 0 terminated */ +extern HTStyleSheet * HTStyleSheet_new (const char * name); +extern BOOL HTStyleSheet_delete (HTStyleSheet * me); - BOOL wordWrap; /* Yes means wrap at space not char */ - BOOL freeFormat; /* Yes means \n is just white space */ - HTCoord spaceBefore; /* Omissions from NXTextStyle */ - HTCoord spaceAfter; - int paraFlags; /* Paragraph flags, bits as follows: */ +/* +. + Creating and Deleting Individual Styles +. +*/ -#define PARA_KEEP 1 /* Do not break page within this paragraph */ -#define PARA_WITH_NEXT 2 /* Do not break page after this paragraph */ +typedef struct _HTStyle HTStyle; -#define HT_JUSTIFY 0 /* For alignment */ -#define HT_LEFT 1 -#define HT_RIGHT 2 -#define HT_CENTER 3 +extern HTStyle * HTStyle_new (const char * name, int element, void * context); +extern BOOL HTStyle_delete (HTStyle * me); -} HTStyle; +/* +. + Adding and Deleting Individual styles from Stylesheet +. +*/ +extern BOOL HTStyleSheet_addStyle (HTStyleSheet * me, HTStyle * style); +extern BOOL HTStyleSheet_deleteStyle (HTStyleSheet * me, HTStyle * style); -/* Style functions: -*/ -extern HTStyle * HTStyleNew NOPARAMS; -extern HTStyle* HTStyleNewNamed PARAMS ((CONST char * name)); -extern HTStyle * HTStyleFree PARAMS((HTStyle * self)); -#ifdef SUPRESS -extern HTStyle * HTStyleRead PARAMS((HTStyle * self, HTStream * stream)); -extern HTStyle * HTStyleWrite PARAMS((HTStyle * self, HTStream * stream)); -#endif -/* Style Sheet -** ----------- +/* +. + Searching for a Specific Style +. */ -typedef struct _HTStyleSheet { - char * name; - HTStyle * styles; -} HTStyleSheet; +extern HTStyle * HTStyleSheet_findStyleWithName (HTStyleSheet * me, const char * name); +extern HTStyle * HTStyleSheet_findStyleForElement (HTStyleSheet * me, int element); -/* Stylesheet functions: +/* */ -extern HTStyleSheet * HTStyleSheetNew NOPARAMS; -extern HTStyleSheet * HTStyleSheetFree PARAMS((HTStyleSheet * self)); -extern HTStyle * HTStyleNamed PARAMS((HTStyleSheet * self, CONST char * name)); -extern HTStyle * HTStyleForParagraph PARAMS((HTStyleSheet * self, - HTParagraphStyle * paraStyle)); -extern HTStyle * HTStyleMatching PARAMS((HTStyleSheet *self, HTStyle * style)); -/* extern HTStyle * HTStyleForRun PARAMS((HTStyleSheet *self, NXRun * run)); */ -extern HTStyleSheet * HTStyleSheetAddStyle PARAMS((HTStyleSheet * self, - HTStyle * style)); -extern HTStyleSheet * HTStyleSheetRemoveStyle PARAMS((HTStyleSheet * self, - HTStyle * style)); -#ifdef SUPPRESS -extern HTStyleSheet * HTStyleSheetRead PARAMS((HTStyleSheet * self, - HTStream * stream)); -extern HTStyleSheet * HTStyleSheetWrite PARAMS((HTStyleSheet * self, - HTStream * stream)); + +#ifdef __cplusplus +} #endif -#define CLEAR_POINTER ((void *)-1) /* Pointer value means "clear me" */ -#endif /* HTStyle_H */ + +#endif /* HTSTYLE_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTTCP.h b/Library/src/HTTCP.h index a3e7436d..e902563a 100644 --- a/Library/src/HTTCP.h +++ b/Library/src/HTTCP.h @@ -1,106 +1,112 @@ -/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/src/HTTCP.html - GENERIC TCP/IP COMMUNICATION - - This module has the common code for handling TCP/IP connections etc. - - */ -#ifndef HTTCP_H -#define HTTCP_H +/* -#include "HTUtils.h" + + W3C Sample Code Library libwww Socket Open and Close -#include "tcp.h" -#ifdef SHORT_NAMES -#define HTInetStatus HTInStat -#define HTInetString HTInStri -#define HTParseInet HTPaInet -#endif +! + Socket Open and Close +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ +/* + +The Socket Open and Close methods knows how to establish a BSD socket TCP +connection and is part of the Transport interface. -/* Produce a string for an internet address -** --------------------------------------- -** -** On exit: -** returns a pointer to a static string which must be copied if -** it is to be kept. +This module is implemented by HTTCP.c, and it is a +part of the W3C Sample Code +Library. */ -#ifdef __STDC__ - extern const char * HTInetString(struct sockaddr_in* sin); -#else - extern char * HTInetString(); -#endif +#ifndef HTTCP_H +#define HTTCP_H +#include "HTReq.h" +#include "HTNet.h" + +#ifdef __cplusplus +extern "C" { +#endif -/* Encode INET status (as in sys/errno.h) inet_status() -** ------------------ -** -** On entry: -** where gives a description of what caused the error -** global errno gives the error number in the unix way. -** -** On return: -** returns a negative status in the unix way. +/* +. + Active Connection Establishment +. + +This makes an active connect to the specified host. An +HTNet Object is parsed in order to handle errors +and other stuff. The default port might be overwritten by any port indication +in the URL specified +as : If it is a multihomed host (a +host having multiple IP-addresses with the same host name)  then +HTDoConnect() measures the time it takes to connect and updates +the calculated weights in the DNS object. */ -#ifdef __STDC__ - extern int HTInetStatus(char *where); -#else - extern int HTInetStatus(); -#endif -/* Publicly accessible variables +extern int HTDoConnect (HTNet * net); + +/* +. + Passive Connection Establishment +. + +This function makes an accept on a port. The net must contain +a valid socket to accept on. If accept is OK then we duplicate the +net object and assign the accepted socket to the newly created net object. +The original Net object will keep accepting connections +on the original socket, for example port 80 in the case of +HTTP. The newly created Net object will be freed +when the protocol module has finished. If the +accepted net object pointer points to the net object itself, that +is - the same object all along - then we reuse the same Net obejct; closes +the original socket and replaces it wik the accepted one. This is a quick +way of accepting a single connection. */ -/* extern struct sockaddr_in HTHostAddress; */ - /* The internet address of the host */ - /* Valid after call to HTHostName() */ - - -/* Parse a cardinal value parse_cardinal() -** ---------------------- -** -** On entry: -** *pp points to first character to be interpreted, terminated by -** non 0..9 character. -** *pstatus points to status already valid, -** maxvalue gives the largest allowable value. -** -** On exit: -** *pp points to first unread character, -** *pstatus points to status updated iff bad + +extern int HTDoAccept (HTNet * listen, HTNet * accept); + +/* +. + Listen on a Socket +. + +Listens on the specified port described in the Net +object. backlog is the number of connections that can be +queued on the socket - you can use HT_BACKLOG for a +platform dependent value (typically 5 on BSD and 32 on SVR4). Returns +HT_ERROR or HT_OK. */ -extern unsigned int HTCardinal PARAMS((int *pstatus, - char **pp, - unsigned int max_value)); - - -/* Parse an internet node address and port -** --------------------------------------- -** -** On entry: -** str points to a string with a node name or number, -** with optional trailing colon and port number. -** sin points to the binary internet or decnet address field. -** -** On exit: -** *sin is filled in. If no port is specified in str, that -** field is left unchanged in *sin. +extern int HTDoListen (HTNet * net, HTNet * accept, int backlog); + +/* +. + Closing a socket +. + +Closes a socket */ -#ifdef __STDC__ - extern int HTParseInet(struct sockaddr_in * sin, CONST char * str); - /*!! had to change this to get it to compile. CTB */ -#else - extern int HTParseInet(); -#endif -/* Get Name of This Machine -** ------------------------ -** +extern int HTDoClose (HTNet * net); + +/* */ -extern CONST char * HTHostName NOPARAMS; +#ifdef __cplusplus +} +#endif #endif /* HTTCP_H */ + /* - End. */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTTP.h b/Library/src/HTTP.h index 90e086a9..552cb052 100644 --- a/Library/src/HTTP.h +++ b/Library/src/HTTP.h @@ -1,29 +1,102 @@ -/* */ +/* -/* HyperText Tranfer Protocol HTTP.h -** ========================== + + W3C Sample Code Library libwww HTTP Client + + +! + Multi Threaded HyperText Tranfer Protocol Client Module +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This is the HTTP client module. This is actually a very small definition +file as almost everything is set up elsewhere. + +This module is implemented by HTTP.c, and it is a part +of the W3C Sample Code Library. */ #ifndef HTTP_H #define HTTP_H -#include "HTAccess.h" +#include "HTProt.h" +#include "HTStream.h" +#ifdef __cplusplus +extern "C" { +#endif + +/* +( + HTTP Client Connection Mode +) -#ifdef OLD_CODE -/* Load Document using HTTP -** ------------------------ +The HTTP client module supports various modes for communicating with HTTP +servers. The mode are defined by the enumeration below. */ -extern int HTLoadHTTP PARAMS(( - CONST char * arg, -/* CONST char * gateway, */ - HTParentAnchor * anAnchor, - int diag)); -#endif -extern HTProtocol HTTP; +typedef enum _HTTPConnectionMode { + HTTP_11_PIPELINING = 0x1, + HTTP_11_NO_PIPELINING = 0x2, + HTTP_11_MUX = 0x4, + HTTP_FORCE_10 = 0x8 +} HTTPConnectionMode; + +extern void HTTP_setConnectionMode (HTTPConnectionMode mode); +extern HTTPConnectionMode HTTP_connectionMode (void); + +/* +( + HTTP Write Delay of Content Bodies +) + +Because of the differences between HTTP/1.0 and HTTP/1.1, HTTP PUT +and POST requests can not be dealt with in non-preemptive mode - +they have to use timers and hence must be in preemptive mode. + +The default write mechanism used is first to write the headers and then wait +for a period of time before writing the body. This often allows the server +to respond before we start sending data accross the wire. If the write for +some reason fails in a bad way then we try again, waiting a little bit longer +this time as this may give the server enough time to think. + +The default wait periods are 2000ms for the first wait and 3000ms if that +fails. These are rather conservative values but can be changed by using these +functions. The second try value must be larger (or equal) to the first try +value and the first try value must be larger than 20 ms. +*/ +extern BOOL HTTP_setBodyWriteDelay (ms_t first_try, ms_t second_try); +extern void HTTP_bodyWriteDelay (ms_t * first_try, ms_t * second_try); + +/* +( + HTTP Event Handler +) + +The event handler is the actual HTTP client state machine taking care of +the communication. +*/ + +extern HTProtCallback HTLoadHTTP; +extern HTConverter HTTPStatus_new; + +#ifdef __cplusplus +} +#endif #endif /* HTTP_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTTeXGen.h b/Library/src/HTTeXGen.h index 6f7253ae..05443cb0 100644 --- a/Library/src/HTTeXGen.h +++ b/Library/src/HTTeXGen.h @@ -1,26 +1,66 @@ -/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTTeXGen.html - TEX GENERATOR - - This module converts structed stream into stream. That is, given a stream to write to, - it will give you a structured stream to - - */ +/* + + W3C Sample Code Library libwww HTML TO LATEX CONVERTER STREAM + + + + +!LaTeX generator! + +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module converts a structured stream from HTML into LaTeX format. The +conversion is mostly a 1:1 translation, but as the LaTeX compiler is much +more strict than a typical HTML converter some typographical constraints +are put on the translation. Only text is translated for the moment. + +This module is implemented by HTTeXGen.c, and +it is a part of the +W3C Sample Code Library. + +*/ + #ifndef HTTEXGEN_H #define HTTEXGEN_H +#include "HTStruct.h" +#include "HTFormat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + +.Conversion Module. -#include "HTML.h" -#include "HTStream.h" +The conversion module is defined as -/* Subclass: */ -/* extern CONST HTStructuredClass HTTeXGeneration; */ -/* Special Creation: +extern HTConverter HTMLToTeX; + +/* + */ -extern HTStructured * HTTeXGenerator PARAMS((HTStream * output)); +#ifdef __cplusplus +} #endif +#endif /* HTTEXGEN_H */ + /* - */ + + +@(#) $Id$ + + +*/ diff --git a/Library/src/HTTelnet.h b/Library/src/HTTelnet.h index 8aa1924d..885f1eae 100644 --- a/Library/src/HTTelnet.h +++ b/Library/src/HTTelnet.h @@ -1,20 +1,49 @@ -/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTTelnet.html - TELNET AND SIMILAR ACCESS METHODS - - */ +/* + + W3C Sample Code Library libwww TELNET, RLOGIN ETC. + + + + +!Telnet and similar access methods! + +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module is implemented by HTTelnet.c, and +it is a part of the W3C +Sample Code Library. + +*/ #ifndef HTTELNET_H #define HTTELNET_H -#include "HTAccess.h" +#include "HTProt.h" + +#ifdef __cplusplus +extern "C" { +#endif -extern HTProtocol HTTelnet; -extern HTProtocol HTRlogin; -extern HTProtocol HTTn3270; +extern HTProtCallback HTLoadTelnet; +#ifdef __cplusplus +} #endif +#endif /* HTTELNET_H */ /* - */ + + +@(#) $Id$ + + +*/ diff --git a/Library/src/HTUtils.h b/Library/src/HTUtils.h index ea689d71..db06d4fe 100644 --- a/Library/src/HTUtils.h +++ b/Library/src/HTUtils.h @@ -1,234 +1,426 @@ -/* */ +/* + + W3C Sample Code Library libwww Debug Information and General Purpose + Macros -/* Macros for general use HTUtils.h -** -** See also: the system dependent file "tcp.h" + +! + Debug Information and General Purpose Macros +! */ -#ifndef DEBUG -#define DEBUG /* Noone ever turns this off as trace is too important */ -#endif /* Keeep option for really small memory applications tho */ - + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This module is a part of the W3C Sample +Code Library. See also the system dependent file +sysdep module for system specific information. +*/ + #ifndef HTUTILS_H #define HTUTILS_H -#ifdef SHORT_NAMES -#define WWW_TraceFlag HTTrFlag -#endif +#ifdef __cplusplus +extern "C" { +#endif -/* Debug message control. +/* +. + Destination for User Print Messages +. + +You can send print messages to the user to various destinations +depending on the type of your application. By default, on Unix the +messages are sent to stdout using +fprintf. If we are on MSWindows and have a windows +applications then register a HTPrintCallback +function. This is done with HTPrint_setCallback. It tells +HTPrint to call a HTPrintCallback. If +HTDEBUG +is not defined then don't do any of the above. */ -#ifndef STDIO_H -#include -#define STDIO_H -#endif -#ifdef DEBUG -#define TRACE (WWW_TraceFlag) -#define PROGRESS(str) printf(str) - extern int WWW_TraceFlag; -#else -#define TRACE 0 -#define PROGRESS(str) /* nothing for now */ -#endif +typedef int HTPrintCallback(const char * fmt, va_list pArgs); +extern void HTPrint_setCallback(HTPrintCallback * pCall); +extern HTPrintCallback * HTPrint_getCallback(void); -#define CTRACE if(TRACE)fprintf -#define tfp stdout +extern int HTPrint(const char * fmt, ...); +/* +. + Debug Message Control +. -/* Standard C library for malloc() etc +This is the global flag for setting the WWWTRACE options. +The verbose mode is no longer a simple boolean but a bit field so that it +is possible to see parts of the output messages. */ -#ifdef vax -#ifdef unix -#define ultrix /* Assume vax+unix=ultrix */ -#endif -#endif -#ifndef VMS -#ifndef ultrix -#ifdef NeXT -#include /* NeXT */ -#endif -#ifndef MACH /* Vincent.Cate@furmint.nectar.cs.cmu.edu */ -#include /* ANSI */ -#endif -#else /* ultrix */ -#include -#include -#include +#if defined(NODEBUG) || defined(NDEBUG) || defined(_NDEBUG) +#undef HTDEBUG +#else +#ifndef HTDEBUG +#define HTDEBUG 1 +#endif /* HTDEBUG */ #endif -#else /* VMS */ -#include -#include +/* +( + C Preprocessor defines +) + +Make sure that the following macros are defined +*/ + +#ifndef __FILE__ +#define __FILE__ "" #endif -#define PUBLIC /* Accessible outside this module */ -#define PRIVATE static /* Accessible only within this module */ - -#ifdef __STDC__ -#define CONST const /* "const" only exists in STDC */ -#define NOPARAMS (void) -#define PARAMS(parameter_list) parameter_list -#define NOARGS (void) -#define ARGS1(t,a) \ - (t a) -#define ARGS2(t,a,u,b) \ - (t a, u b) -#define ARGS3(t,a,u,b,v,c) \ - (t a, u b, v c) -#define ARGS4(t,a,u,b,v,c,w,d) \ - (t a, u b, v c, w d) -#define ARGS5(t,a,u,b,v,c,w,d,x,e) \ - (t a, u b, v c, w d, x e) -#define ARGS6(t,a,u,b,v,c,w,d,x,e,y,f) \ - (t a, u b, v c, w d, x e, y f) -#define ARGS7(t,a,u,b,v,c,w,d,x,e,y,f,z,g) \ - (t a, u b, v c, w d, x e, y f, z g) -#define ARGS8(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h) \ - (t a, u b, v c, w d, x e, y f, z g, s h) -#define ARGS9(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i) \ - (t a, u b, v c, w d, x e, y f, z g, s h, r i) -#define ARGS10(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i,q,j) \ - (t a, u b, v c, w d, x e, y f, z g, s h, r i, q j) - -#else /* not ANSI */ - -#define CONST -#define NOPARAMS () -#define PARAMS(parameter_list) () -#define NOARGS () -#define ARGS1(t,a) (a) \ - t a; -#define ARGS2(t,a,u,b) (a,b) \ - t a; u b; -#define ARGS3(t,a,u,b,v,c) (a,b,c) \ - t a; u b; v c; -#define ARGS4(t,a,u,b,v,c,w,d) (a,b,c,d) \ - t a; u b; v c; w d; -#define ARGS5(t,a,u,b,v,c,w,d,x,e) (a,b,c,d,e) \ - t a; u b; v c; w d; x e; -#define ARGS6(t,a,u,b,v,c,w,d,x,e,y,f) (a,b,c,d,e,f) \ - t a; u b; v c; w d; x e; y f; -#define ARGS7(t,a,u,b,v,c,w,d,x,e,y,f,z,g) (a,b,c,d,e,f,g) \ - t a; u b; v c; w d; x e; y f; z g; -#define ARGS8(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h) (a,b,c,d,e,f,g,h) \ - t a; u b; v c; w d; x e; y f; z g; s h; -#define ARGS9(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i) (a,b,c,d,e,f,g,h,i) \ - t a; u b; v c; w d; x e; y f; z g; s h; r i; -#define ARGS10(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i,q,j) (a,b,c,d,e,f,g,h,i,j) \ - t a; u b; v c; w d; x e; y f; z g; s h; r i q j; - - -#endif /* __STDC__ (ANSI) */ - -#ifndef NULL -#define NULL ((void *)0) +#ifndef __LINE__ +#define __LINE__ 0L #endif +/* +( + Definition of the Global Trace Flag +) -/* Note: GOOD and BAD are already defined (differently) on RS6000 aix */ -/* #define GOOD(status) ((status)&1) VMS style status: test bit 0 */ -/* #define BAD(status) (!GOOD(status)) Bit 0 set if OK, otherwise clear */ +The global trace flag variable is available everywhere. +*/ -#ifndef BOOLEAN_DEFINED - typedef char BOOLEAN; /* Logical value */ -#ifndef CURSES -#ifndef TRUE -#define TRUE (BOOLEAN)1 -#define FALSE (BOOLEAN)0 -#endif -#endif -#define BOOLEAN_DEFINED -#endif +#ifdef HTDEBUG +#ifdef WWW_WIN_DLL +extern int * WWW_TraceFlag; /* In DLLs, we need the indirection */ +#define WWWTRACE (*WWW_TraceFlag) +#else +extern unsigned int WWW_TraceFlag; /* Global flag for all W3 trace */ +#define WWWTRACE (WWW_TraceFlag) +#endif /* WWW_WIN_DLL */ +#else +#define WWWTRACE 0 +#endif /* HTDEBUG */ -#ifndef BOOL -#define BOOL BOOLEAN -#endif -#ifndef YES -#define YES (BOOLEAN)1 -#define NO (BOOLEAN)0 -#endif +/* +( + Select which Trace Messages to show +) + +Libwww has a huge set of trace messages and it is therefor a good idea to +be able to select which ones to see for any particular trace. An easy way +to set this is using the funtion +HTSetTraceMessageMask. The WWWTRACE +define outputs messages if verbose mode is active according to the following +rules: +*/ -#ifndef min -#define min(a,b) ((a) <= (b) ? (a) : (b)) -#define max(a,b) ((a) >= (b) ? (a) : (b)) -#endif +typedef enum _HTTraceFlags { + SHOW_UTIL_TRACE = 0x1, + SHOW_APP_TRACE = 0x2, + SHOW_CACHE_TRACE = 0x4, + SHOW_SGML_TRACE = 0x8, + SHOW_BIND_TRACE = 0x10, + SHOW_THREAD_TRACE = 0x20, + SHOW_STREAM_TRACE = 0x40, + SHOW_PROTOCOL_TRACE = 0x80, + SHOW_MEM_TRACE = 0x100, + SHOW_URI_TRACE = 0x200, + SHOW_AUTH_TRACE = 0x400, + SHOW_ANCHOR_TRACE = 0x800, + SHOW_PICS_TRACE = 0x1000, + SHOW_CORE_TRACE = 0x2000, + SHOW_MUX_TRACE = 0x4000, + SHOW_SQL_TRACE = 0x8000, + SHOW_XML_TRACE = 0x10000, + SHOW_ALL_TRACE = (int) 0xFFFFFFFF +} HTTraceFlags; -#define TCP_PORT 80 /* Allocated to http by Jon Postel/ISI 24-Jan-92 */ -#define OLD_TCP_PORT 2784 /* Try the old one if no answer on 80 */ -#define DNP_OBJ 80 /* This one doesn't look busy, but we must check */ +/* -/* Inline Function WHITE: Is character c white space? */ -/* For speed, include all control characters */ +The flags are made so that they can serve as a group flag for correlated +trace messages, e.g. showing messages for SGML and HTML at the same time. +*/ -#define WHITE(c) (((unsigned char)(TOASCII(c)))<=32) +#define UTIL_TRACE (WWWTRACE & SHOW_UTIL_TRACE) +#define APP_TRACE (WWWTRACE & SHOW_APP_TRACE) +#define CACHE_TRACE (WWWTRACE & SHOW_CACHE_TRACE) +#define SGML_TRACE (WWWTRACE & SHOW_SGML_TRACE) +#define BIND_TRACE (WWWTRACE & SHOW_BIND_TRACE) +#define THD_TRACE (WWWTRACE & SHOW_THREAD_TRACE) +#define STREAM_TRACE (WWWTRACE & SHOW_STREAM_TRACE) +#define PROT_TRACE (WWWTRACE & SHOW_PROTOCOL_TRACE) +#define MEM_TRACE (WWWTRACE & SHOW_MEM_TRACE) +#define URI_TRACE (WWWTRACE & SHOW_URI_TRACE) +#define AUTH_TRACE (WWWTRACE & SHOW_AUTH_TRACE) +#define ANCH_TRACE (WWWTRACE & SHOW_ANCHOR_TRACE) +#define PICS_TRACE (WWWTRACE & SHOW_PICS_TRACE) +#define CORE_TRACE (WWWTRACE & SHOW_CORE_TRACE) +#define MUX_TRACE (WWWTRACE & SHOW_MUX_TRACE) +#define SQL_TRACE (WWWTRACE & SHOW_SQL_TRACE) +#define XML_TRACE (WWWTRACE & SHOW_XML_TRACE) +#define ALL_TRACE (WWWTRACE & SHOW_ALL_TRACE) +/* +( + Destination for Trace Messages +) + +You can send trace messages to various destinations depending on the type +of your application. By default, on Unix the messages are sent to +stderr using fprintf. If we are on MSWindows and +have a windows applications then register a HTTraceCallback +function. This is done with HTTrace_setCallback. It tells +HTTrace to call a HTTraceCallback. If +HTDEBUG is not defined then don't do any of the above. +*/ + +typedef int HTTraceCallback(const char * fmt, va_list pArgs); +extern void HTTrace_setCallback(HTTraceCallback * pCall); +extern HTTraceCallback * HTTrace_getCallback(void); + +/* + +The HTTRACE macro uses "_" as parameter separater +instead of ",". This enables us to use a single macro instead +of a macro for each number of arguments which we consider a more elegant +and flexible solution. The implication is, however, that we can't have variables +that start or end with an "_" if they are to be used in a trace +message. +*/ + +#ifdef HTDEBUG +#undef _ +#define _ , +#define HTTRACE(TYPE, FMT) \ + do { if (TYPE) HTTrace(FMT); } while (0); +extern int HTTrace(const char * fmt, ...); +#else +#define HTTRACE(TYPE, FMT) /* empty */ +#endif /* HTDEBUG */ + +/* +( + Data Trace Logging +) -/* Sucess (>=0) and failure (<0) codes +A similar mechanism exists for logging data, except that is adds a data and +length argument to the trace call. Again, you can register your own callbacks +if need be. */ -#define HT_LOADED 29999 /* Instead of a socket */ -#define HT_OK 0 /* Generic success*/ -#define HT_NO_ACCESS -10 /* Access not available */ -#define HT_FORBIDDEN -11 /* Access forbidden */ -#define HT_INTERNAL -12 /* Weird -- should never happen. */ -#define HT_BAD_EOF -12 /* Premature EOF */ +typedef int HTTraceDataCallback(char * data, size_t len, char * fmt, va_list pArgs); +extern void HTTraceData_setCallback(HTTraceDataCallback * pCall); +extern HTTraceDataCallback * HTTraceData_getCallback(void); -#include "HTString.h" /* String utilities */ +/* + +Again we use the same macro expansion mechanism as for HTTrace +*/ -#ifdef __STDC__ -#include +#ifdef HTDEBUG +#define HTTRACEDATA(DATA, LEN, FMT) HTTraceData((DATA), (LEN), FMT) +extern int HTTraceData(char * data, size_t len, char * fmt, ...); #else -#include -#endif +#define HTTRACEDATA(DATA, LEN, FMT) /* empty */ +#endif /* HTDEBUG */ -#ifdef CURSES - /* htbrowse.c; */ -#include +/* +( + Debug Breaks +) + +Call this function and the program halts. We use the same macro expansion +mechanism as for HTTrace +*/ - extern WINDOW *w_top, *w_text, *w_prompt; - extern void user_message PARAMS((const char *fmt, ...)); - extern void prompt_set PARAMS((CONST char * msg)); - extern void prompt_count PARAMS((long kb)); +extern void HTDebugBreak(char * file, unsigned long line, const char * fmt, ...); + +#ifdef HTDEBUG +#define HTDEBUGBREAK(FMT) HTDebugBreak(__FILE__, __LINE__, FMT) #else -#define user_message printf +#define HTDEBUGBREAK(FMT) /* empty */ +#endif /* HTDEBUG */ + +/* +. + Macros for Function Declarations +. + +These function prefixes are used by scripts and other tools and helps figuring +out which functions are exported and which are not. See also the +libwww style guide. +*/ + +#define PUBLIC /* Accessible outside this module */ +#define PRIVATE static /* Accessible only within this module */ + +/* +. + Often used Interger Macros +. +( + Min and Max functions +) +*/ + +#ifndef HTMIN +#define HTMIN(a,b) ((a) <= (b) ? (a) : (b)) +#define HTMAX(a,b) ((a) >= (b) ? (a) : (b)) #endif -/* Out Of Memory checking for malloc() return: +/* +( + Double abs function +) */ -#ifndef __FILE__ -#define __FILE__ "" -#define __LINE__ "" + +#ifndef HTDABS +#define HTDABS(a) ((a) < 0.0 ? (-(a)) : (a)) #endif -#define outofmem(file, func) \ - { fprintf(stderr, "%s %s: out of memory.\nProgram aborted.\n", file, func); \ - exit(1);} -/* extern void outofmem PARAMS((const char *fname, const char *func)); */ +/* -extern void msg_init PARAMS((int height)); -extern void msg_printf PARAMS((int y, const char *fmt, ...)); -extern void msg_exit PARAMS((int wait_for_key)); +. + Return Codes for Protocol Modules and Streams +. -/* Upper- and Lowercase macros -** -** The problem here is that toupper(x) is not defined officially unless -** isupper(x) is. These macros are CERTAINLY needed on -** #if defined(pyr) || define(mips) or BDSI platforms. -** For safefy, we make them mandatory. +Theese are the codes returned from the protocol modules, and the stream modules. +Success are (>=0) and failure are (<0) */ -#include +#define HT_OK 0 /* Generic success */ +#define HT_ALL 1 /* Used by Net Manager */ + +#define HT_CONTINUE 100 /* Continue an operation */ +#define HT_UPGRADE 101 /* Switching protocols */ + +#define HT_LOADED 200 /* Everything's OK */ +#define HT_CREATED 201 /* New object is created */ +#define HT_ACCEPTED 202 /* Accepted */ +#define HT_NO_DATA 204 /* OK but no data was loaded */ +#define HT_RESET_CONTENT 205 /* Reset content */ +#define HT_PARTIAL_CONTENT 206 /* Partial Content */ + +#define HT_MULTIPLE_CHOICES 300 /* Multiple choices */ +#define HT_PERM_REDIRECT 301 /* Permanent redirection */ +#define HT_FOUND 302 /* Found */ +#define HT_SEE_OTHER 303 /* See other */ +#define HT_NOT_MODIFIED 304 /* Not Modified */ +#define HT_USE_PROXY 305 /* Use Proxy */ +#define HT_PROXY_REDIRECT 306 /* Proxy Redirect */ +#define HT_TEMP_REDIRECT 307 /* Temporary redirect */ + +#define HT_IGNORE 900 /* Ignore this in the Net manager */ +#define HT_CLOSED 901 /* The socket was closed */ +#define HT_PENDING 902 /* Wait for connection */ +#define HT_RELOAD 903 /* If we must reload the document */ + +#define HT_ERROR -1 /* Generic failure */ + +#define HT_NO_ACCESS -401 /* Unauthorized */ +#define HT_FORBIDDEN -403 /* Access forbidden */ +#define HT_NOT_FOUND -404 /* Not found */ +#define HT_NOT_ACCEPTABLE -406 /* Not Acceptable */ +#define HT_NO_PROXY_ACCESS -407 /* Proxy Authentication Failed */ +#define HT_CONFLICT -409 /* Conflict */ +#define HT_LENGTH_REQUIRED -411 /* Length required */ +#define HT_PRECONDITION_FAILED -412 /* Precondition failed */ +#define HT_TOO_BIG -413 /* Request entity too large */ +#define HT_URI_TOO_BIG -414 /* Request-URI too long */ +#define HT_UNSUPPORTED -415 /* Unsupported */ +#define HT_BAD_RANGE -416 /* Request Range not satisfiable */ +#define HT_EXPECTATION_FAILED -417 /* Expectation Failed */ +#define HT_REAUTH -418 /* Reauthentication required */ +#define HT_PROXY_REAUTH -419 /* Proxy Reauthentication required */ + +#define HT_RETRY -503 /* If service isn't available */ +#define HT_BAD_VERSION -505 /* Bad protocol version */ + +#ifdef HT_DAV /* WebDAV Status codes */ +#define HT_PROCESSING 102 /* Processing */ +#define HT_MULTI_STATUS 207 /* Multi-Status */ +#define HT_UNPROCESSABLE -422 /* Unprocessable Entity */ +#define HT_LOCKED -423 /* Locked */ +#define HT_FAILED_DEPENDENCY -424 /* Failed Dependency */ +#define HT_INSUFFICIENT_STORAGE -507 /* Insufficient Storage */ +#endif + +#define HT_INTERNAL -900 /* Weird -- should never happen. */ +#define HT_WOULD_BLOCK -901 /* If we are in a select */ +#define HT_INTERRUPTED -902 /* Note the negative value! */ +#define HT_PAUSE -903 /* If we want to pause a stream */ +#define HT_RECOVER_PIPE -904 /* Recover pipe line */ +#define HT_TIMEOUT -905 /* Connection timeout */ +#define HT_NO_HOST -906 /* Can't locate host */ + +/* +. + Upper- and Lowercase macros +. + +The problem here is that toupper(x) is not defined officially unless isupper(x) +is. These macros are CERTAINLY needed on #if defined(pyr) || define(mips) +or BDSI platforms. For safefy, we make them mandatory. +*/ #ifndef TOLOWER - /* Pyramid and Mips can't uppercase non-alpha */ -#define TOLOWER(c) (isupper(c) ? tolower(c) : (c)) -#define TOUPPER(c) (islower(c) ? toupper(c) : (c)) -#endif /* ndef TOLOWER */ +#define TOLOWER(c) tolower((int) (c)) +#define TOUPPER(c) toupper((int) (c)) +#endif + +/* +. + Max and Min values for Integers and Floating Point +. +*/ + +#ifdef FLT_EPSILON /* The ANSI C way define */ +#define HT_EPSILON FLT_EPSILON +#else +#define HT_EPSILON 0.00000001 +#endif + +/* +. + The local equivalents of CR and LF +. + +We can check for these after net ascii text has been converted to the local +representation. Similarly, we include them in strings to be sent as net ascii +after translation. +*/ + +#define LF FROMASCII('\012') /* ASCII line feed LOCAL EQUIVALENT */ +#define CR FROMASCII('\015') /* Will be converted to ^M for transmission */ -#endif /* HTUTILS_H */ +/* +. + Library Dynamic Memory Magement +. + +The Library has it's own dynamic memory API which is declared in +memory management module. +*/ + +#include "HTMemory.h" /* +*/ + +#ifdef __cplusplus +} +#endif - */ +#endif /* HT_UTILS.h */ + +/* + + + + @(#) $Id$ + +*/ diff --git a/Library/src/HTWriter.h b/Library/src/HTWriter.h index 9fa5f8c6..9e538c4b 100644 --- a/Library/src/HTWriter.h +++ b/Library/src/HTWriter.h @@ -1,28 +1,70 @@ -/* */ - -/* Unix File or Socket Writer HTWriter.c -** -------------------------- -** -** This version of the stream object just writes to a socket. -** The socket is assumed open and closed afterward. -** -** There are two versions (identical on ASCII machines) -** one of which converts to ASCII on output. -** -** Bugs: -** strings written must be less than buffer size. +/* + + + W3C Sample Code Library libwww Unbuffered Socket Writer Stream + + +! + Unbuffered Socket Writer Stream +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +The Socket Writer Stream is an output stream + which knows how to write to a BSD type socket. It is part of the +Transport interface and may be registered as +part of a Transport Object. The application +can initialize this stream together with the +HTReader stream, for example. In the +default initialization module, you can find the +HTTransportInit() function which sets up this stream as a default +transport for handling unbuffered socket write operations. See also the +buffered writer stream. + +This module is implemented by HTWriter.c, and it +is a part of the W3C Sample Code +Library. */ #ifndef HTWRITE_H #define HTWRITE_H -#include "HTStream.h" +#include "HTIOStream.h" -extern HTStream * HTWriter_new PARAMS((int soc)); +#ifdef __cplusplus +extern "C" { +#endif -extern HTStream * HTASCIIWriter PARAMS((int soc)); +/* +*/ +extern HTOutput_new HTWriter_new; + +extern BOOL HTWriter_set (HTOutputStream * me, + HTNet * net, + HTChannel * ch, + void * param, + int mode); + + +/* +*/ +#ifdef __cplusplus +} #endif + +#endif /* HTWRITE_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/HText.h b/Library/src/HText.h index aa9e70a7..d517b1ad 100644 --- a/Library/src/HText.h +++ b/Library/src/HText.h @@ -1,176 +1,299 @@ -/* */ +/* + + W3C Sample Code Library libwww Rich Hypertext Object -/* HyperText Object HText.h -** ================ -** This is the C interface to the Objective-C HyperText class. + +! + HyperText Object Builder +! +*/ + +/* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ + +/* + +This is the interface that  you can use to build a parsed HTML object +(called an hypertext object) as output of the libwww +HTML parser. It is based on callback functions that the application can +register as needed in order to get the various events out of the HTML parser. +These are the different events that can be registered: + + + o + When parsing is about to start or terminate + o + When a chunk of plain text has been found + o + When a link has been found in some HTML element + o + When an HTML element is about to start or end + o + Handler for unparsed elements + o + Handler for unparsed entities + + +Building an hypertext object can contain references to stylesheets. Libwww +doesn't come with a stylesheet implementation but it does have a +generic stylesheet manager which can be used for +registering and looking up styles. As an example, you can see how the libwww +robot uses the link callout whereas +the Line Mode Browser has a complete +implementation in the +GridText module. */ #ifndef HTEXT_H #define HTEXT_H + #include "HTAnchor.h" -#include "HTStyle.h" #include "HTStream.h" -#ifdef SHORT_NAMES -#define HTMainText HTMaText -#define HTMainAnchor HtMaAnch -#define HText_new HTHTNew -#define HText_free HTHTFree -#define HText_beginAppend HTHTBeAp -#define HText_endAppend HTHTEnAp -#define HText_setStyle HTHTSeSt -#define HText_appendCharacter HTHTApCh -#define HText_appendText HTHTApTe -#define HText_appendParagraph HTHTApPa -#define HText_beginAnchor HTHTBeAn -#define HText_endAnchor HTHTEnAn -#define HText_dump HTHTDump -#define HText_nodeAnchor HTHTNoAn -#define HText_select HTHTSele -#define HText_selectAnchor HTHTSeAn -#define HText_applyStyle HTHTApSt -#define HText_updateStyle HTHTUpSt -#define HText_selectionStyle HTHTStyl -#define HText_replaceSel HTHTRepl -#define HText_applyToSimilar HTHTApTo -#define HText_selectUnstyled HTHTSeUn -#define HText_unlinkSelection HTHTUnSe -#define HText_linkSelTo HTHTLiSe -#define HText_referenceSelected HTHTRefS -#endif +#ifdef __cplusplus +extern "C" { +#endif -#ifndef THINK_C -#ifndef HyperText /* Objective C version defined HyperText */ -typedef struct _HText HText; /* Normal Library */ -#endif -#else -class CHyperText; /* Mac Think-C browser hook */ -typedef CHyperText HText; -#endif +/* +. + The HText Object +. + +The HText object is only known as a name to libwww - it isn't defined +or used anywhere as an actual structure. The application can use the HText +object to contain the information needed to build a parsed object - a hypertext +object - as data arrives from the libwww HTML parser. +When a HText object is to be created, this module calls out to any registered +creation method and in turn uses the newly created HText object in every +subsequent call to any registered callback routine as the HTML stream is +parsed. +*/ -extern HText * HTMainText; /* Pointer to current main text */ -extern HTParentAnchor * HTMainAnchor; /* Pointer to current text's anchor */ +typedef struct _HText HText; -/* Creation and deletion -** -** Create hypertext object HText_new +/* +. + Callback for Creating and Deleting an HText Object +. + +When an HTML stream is created, the +HTML parser checks to see if there are any callbacks +registered for handling the HText object. If this is +the case then the creation callback is called so that the application can +create a new HText object. After that the various callbacks +are called (if registered) as text comes in and +gets parsed. */ - extern HText * HText_new PARAMS((HTParentAnchor * anchor)); - extern HText * HText_new2 PARAMS((HTParentAnchor * anchor, - HTStream * output_stream)); -/* Free hypertext object HText_free -*/ -extern void HText_free PARAMS((HText * me)); +typedef HText * HText_new ( + HTRequest * request, + HTParentAnchor * anchor, + HTStream * output_stream); +typedef BOOL HText_delete (HText * me); -/* Object Building methods -** ----------------------- -** -** These are used by a parser to build the text in an object -** HText_beginAppend must be called, then any combination of other -** append calls, then HText_endAppend. This allows optimised -** handling using buffers and caches which are flushed at the end. +/* +( + Register Creation/Deletion Callbacks +) */ -extern void HText_beginAppend PARAMS((HText * text)); -extern void HText_endAppend PARAMS((HText * text)); +extern BOOL HText_registerCDCallback (HText_new *, HText_delete *); +extern BOOL HText_unregisterCDCallback (void); -/* Set the style for future text +/* +. + Callback for Start and Terminate Parsing +. + +The call sequence is the following: First HText_build is called +with the status of HTEXT_BEGIN, then any combination of other append +calls, and at the end HText_build is called with the termination +status - if it terminated normally then the status is HTEXT_END, +if the download was aborted the status is HTEXT_ABORT. */ -extern void HText_setStyle PARAMS((HText * text, HTStyle * style)); -/* Add one character -*/ -extern void HText_appendCharacter PARAMS((HText * text, char ch)); +typedef enum _HTextStatus { + HTEXT_BEGIN, + HTEXT_END, + HTEXT_ABORT +} HTextStatus; -/* Add a zero-terminated string -*/ -extern void HText_appendText PARAMS((HText * text, CONST char * str)); +typedef void HText_build (HText * text, HTextStatus status); -/* New Paragraph +/* +( + Register Start/End Callback +) */ -extern void HText_appendParagraph PARAMS((HText * text)); -/* Start/end sensitive text -** -** The anchor object is created and passed to HText_beginAnchor. -** The senstive text is added to the text object, and then HText_endAnchor -** is called. Anchors may not be nested. -*/ +extern BOOL HText_registerBuildCallback (HText_build *); +extern BOOL HText_unregisterBuildCallback (void); -extern void HText_beginAnchor PARAMS((HText * text, HTChildAnchor * anc)); -extern void HText_endAnchor PARAMS((HText * text)); +/* +. + Callback for Handling Chunks of Text +. + +THE STRING IS NOT ZERO-TERMINATED!!! When plain text is +found then it can be passed to the application via this function. HTML text +is already stripped for unneeded white space whereas literal text isn't. +The text is of course to be taken "relative" to which element is is found +within - this is not checked by the HTML parser but can be checked by the +application by using the Element callback function. +*/ +typedef void HText_addText ( + HText * text, + const char * buffer, + int length); -/* Dump diagnostics to stderr +/* +( + Register Text Callback +) */ -extern void HText_dump PARAMS((HText * me)); -/* Return the anchor associated with this node +extern BOOL HText_registerTextCallback (HText_addText *); +extern BOOL HText_unregisterTextCallback (void); + +/* +. + Callback for Handling Hypertext Links +. + +Whenever a link is found in the HTML stream, be it from an anchor element, +an inlined image, etc. then it is picked up and this called out to this function +with the parameters necessary to be able to see what type of link it is (the +element and the name of the attribute where it was found). The element number +and attribute number are integers that are defined by the +HTML DTD used by the HTMl parser. The +present and value arrays contains all the +SGML attributes and values found in the element +untouched. Again, the array is defined by the HTML +DTD used by the HTML parser. */ -extern HTParentAnchor * HText_nodeAnchor PARAMS((HText * me)); +typedef void HText_foundLink ( + HText * text, + int element_number, + int attribute_number, + HTChildAnchor * anchor, + const BOOL * present, + const char ** value); -/* Browsing functions -** ------------------ +/* +( + Register Link Callback +) */ -/* Bring to front and highlight it +extern BOOL HText_registerLinkCallback (HText_foundLink *); +extern BOOL HText_unregisterLinkCallback (void); + +/* +. + Callback for Handling HTML Elements +. + +Whenever an element is found in the HTML stream, be it an IMG element, a +BODY element, etc. then it is picked up and this called out to this function +with the parameters necessary to be able to see what type of element it is. +The element number and attribute number are integers that are defined by +the HTML DTD used by the HTMl parser. The +present and value arrays contains all the +SGML attributes and values found in the element +untouched. Again, the array is defined by the HTML +DTD used by the HTML parser. */ -extern BOOL HText_select PARAMS((HText * text)); -extern BOOL HText_selectAnchor PARAMS((HText * text, HTChildAnchor* anchor)); +typedef void HText_beginElement ( + HText * text, + int element_number, + const BOOL * present, + const char ** value); -/* Editing functions -** ----------------- -** -** These are called from the application. There are many more functions -** not included here from the orginal text object. These functions -** NEED NOT BE IMPLEMENTED in a browser which cannot edit. -*/ +typedef void HText_endElement ( + HText * text, + int element_number); -/* Style handling: -*/ -/* Apply this style to the selection +/* +( + Register HTML Element Callback +) */ -extern void HText_applyStyle PARAMS((HText * me, HTStyle *style)); -/* Update all text with changed style. -*/ -extern void HText_updateStyle PARAMS((HText * me, HTStyle *style)); +extern BOOL HText_registerElementCallback (HText_beginElement *, HText_endElement *); +extern BOOL HText_unregisterElementCallback (void); -/* Return style of selection +/* +. + Callback for Unparsed Elements +. + +Whenever an element is found which is not known by the HTML DTD, then the +information is passed to the unparsed element handlers. */ -extern HTStyle * HText_selectionStyle PARAMS(( - HText * me, - HTStyleSheet* sheet)); -/* Paste in styled text +typedef void HText_unparsedBeginElement ( + HText * HText, + const char * buffer, + int length); + +typedef void HText_unparsedEndElement ( + HText * HText, + const char * buffer, + int length); + +/* +( + Register Unparsed Element Callback +) */ -extern void HText_replaceSel PARAMS((HText * me, - CONST char *aString, - HTStyle* aStyle)); -/* Apply this style to the selection and all similarly formatted text -** (style recovery only) +extern BOOL HText_registerUnparsedElementCallback ( + HText_unparsedBeginElement *, + HText_unparsedEndElement *); +extern BOOL HText_unregisterUnparsedElementCallback (void); + +/* +. + Callback for Unparsed Entity +. + +Whenever an entity is found which is not known by the HTML DTD, then the +information is passed to the default handler. */ -extern void HTextApplyToSimilar PARAMS((HText * me, HTStyle *style)); -/* Select the first unstyled run. -** (style recovery only) +typedef void HText_unparsedEntity ( + HText * HText, + const char * buffer, + int length); + +/* +( + Register Unparsed Entity Callback +) */ -extern void HTextSelectUnstyled PARAMS((HText * me, HTStyleSheet *sheet)); +extern BOOL HText_registerUnparsedEntityCallback (HText_unparsedEntity *); +extern BOOL HText_unregisterUnparsedEntityCallback (void); -/* Anchor handling: +/* */ -extern void HText_unlinkSelection PARAMS((HText * me)); -extern HTAnchor * HText_referenceSelected PARAMS((HText * me)); -extern HTAnchor * HText_linkSelTo PARAMS((HText * me, HTAnchor* anchor)); +#ifdef __cplusplus +} +#endif #endif /* HTEXT_H */ + /* - */ + + + @(#) $Id$ + +*/ diff --git a/Library/src/SGML.h b/Library/src/SGML.h index c052529f..996074e6 100644 --- a/Library/src/SGML.h +++ b/Library/src/SGML.h @@ -1,184 +1,157 @@ -/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/SGML.html - SGML AND STRUCTURED STREAMS - - The SGML parser is a state machine. It is called for every character - - of the input stream. The DTD data structure contains pointers - - to functions which are called to implement the actual effect of the - - text read. When these functions are called, the attribute structures pointed to by the - DTD are valid, and the function is passed a pointer to the curent tag structure, and an - "element stack" which represents the state of nesting within SGML elements. - - The following aspects are from Dan Connolly's suggestions: Binary search, Strcutured - object scheme basically, SGML content enum type. - - (c) Copyright CERN 1991 - See Copyright.html - - */ -#ifndef SGML_H -#define SGML_H +/* + + + W3C Sample Code Library libwww SGML Parser -#include "HTUtils.h" -#include "HTStream.h" + +! + SGML Parser +! +*/ /* +** (c) COPYRIGHT MIT 1995. +** Please first read the full copyright statement in the file COPYRIGH. +*/ -SGML content types +/* - */ -typedef enum _SGMLContent{ - SGML_EMPTY, /* no content */ - SGML_LITTERAL, /* character data. Recognised excat close tag only. litteral - Old www server compatibility only! Not SGML */ - SGML_CDATA, /* character data. recognize =4.1 -O3. #1983953, 2517952, 2517962, 2649838: Build modifications using autoreconf instead of buildconf.sh. #2815947, #2884086: OBJEXT and EXEEXT support while building. - #1990430: CVE-2009-3720 - Parser crash with special UTF-8 sequences. #2517938: xmlwf should return non-zero exit status if not well-formed. #2517946: Wrong statement about XMLDecl in xmlwf.1 and xmlwf.sgml. #2855609: Dangling positionPtr after error. - #2894085: CVE-2009-3560 - Buffer over-read and crash in big2_toUtf8(). - #2958794: CVE-2012-1148 - Memory leak in poolGrow. #2990652: CMake support. #3010819: UNEXPECTED_STATE with a trailing "%" in entity value. #3206497: Unitialized memory returned from XML_Parse. #3287849: make check fails on mingw-w64. - #3496608: CVE-2012-0876 - Hash DOS attack. - Patches: #1749198: pkg-config support. #3010222: Fix for bug #3010819. diff --git a/modules/expat/MANIFEST b/modules/expat/MANIFEST index afb9acac..c8479ed0 100644 --- a/modules/expat/MANIFEST +++ b/modules/expat/MANIFEST @@ -1,44 +1,4 @@ -amiga/launch.c -amiga/expat_68k.c -amiga/expat_68k.h -amiga/expat_68k_handler_stubs.c -amiga/expat_base.h -amiga/expat_vectors.c -amiga/expat_lib.c -amiga/expat.xml -amiga/README.txt -amiga/Makefile -amiga/include/proto/expat.h -amiga/include/libraries/expat.h -amiga/include/interfaces/expat.h -amiga/include/inline4/expat.h -bcb5/README.txt -bcb5/all_projects.bpg -bcb5/elements.bpf -bcb5/elements.bpr -bcb5/elements.mak -bcb5/expat.bpf -bcb5/expat.bpr -bcb5/expat.mak -bcb5/expat_static.bpf -bcb5/expat_static.bpr -bcb5/expat_static.mak -bcb5/expatw.bpf -bcb5/expatw.bpr -bcb5/expatw.mak -bcb5/expatw_static.bpf -bcb5/expatw_static.bpr -bcb5/expatw_static.mak -bcb5/libexpat_mtd.def -bcb5/libexpatw_mtd.def -bcb5/makefile.mak -bcb5/outline.bpf -bcb5/outline.bpr -bcb5/outline.mak -bcb5/setup.bat -bcb5/xmlwf.bpf -bcb5/xmlwf.bpr -bcb5/xmlwf.mak +AUTHORS doc/expat.png doc/reference.html doc/style.css @@ -58,8 +18,8 @@ configure.ac expat_config.h.in expat_config.h.cmake expat.pc.in -expat.dsw aclocal.m4 +run.sh.in conftools/PrintPath conftools/ac_c_bigendian_cross.m4 conftools/expat.m4 @@ -75,26 +35,18 @@ m4/ltoptions.m4 m4/ltsugar.m4 m4/lt~obsolete.m4 examples/elements.c -examples/elements.dsp examples/outline.c -examples/outline.dsp -lib/Makefile.MPW -lib/amigaconfig.h lib/ascii.h lib/asciitab.h -lib/expat.dsp lib/expat.h lib/expat_external.h -lib/expat_static.dsp -lib/expatw.dsp -lib/expatw_static.dsp lib/iasciitab.h lib/internal.h lib/latin1tab.h lib/libexpat.def lib/libexpatw.def -lib/macconfig.h lib/nametab.h +lib/siphash.h lib/utf8tab.h lib/winconfig.h lib/xmlparse.c @@ -107,19 +59,16 @@ lib/xmltok_impl.h lib/xmltok_ns.c tests/benchmark/README.txt tests/benchmark/benchmark.c -tests/benchmark/benchmark.dsp -tests/benchmark/benchmark.dsw tests/README.txt tests/chardata.c tests/chardata.h +tests/memcheck.c +tests/memcheck.h tests/minicheck.c tests/minicheck.h tests/runtests.c tests/runtestspp.cpp tests/xmltest.sh -vms/README.vms -vms/descrip.mms -vms/expat_config.h win32/MANIFEST.txt win32/README.txt win32/expat.iss @@ -137,5 +86,4 @@ xmlwf/xmlmime.h xmlwf/xmltchar.h xmlwf/xmlurl.h xmlwf/xmlwf.c -xmlwf/xmlwf.dsp xmlwf/xmlwin32url.cxx diff --git a/modules/expat/Makefile.in b/modules/expat/Makefile.in index 3310aa9a..3ee11e85 100644 --- a/modules/expat/Makefile.in +++ b/modules/expat/Makefile.in @@ -57,8 +57,8 @@ clean: cd lib && rm -f $(LIBRARY) *.@OBJEXT@ *.lo && rm -rf .libs _libs cd xmlwf && rm -f xmlwf *.@OBJEXT@ *.lo && rm -rf .libs _libs cd examples && rm -f elements outline *.@OBJEXT@ *.lo && rm -rf .libs _libs - cd tests && rm -rf .libs runtests runtests.@OBJEXT@ runtestspp runtestspp.@OBJEXT@ - cd tests && rm -f chardata.@OBJEXT@ minicheck.@OBJEXT@ + cd tests && rm -rf .libs runtests@EXEEXT@ runtests.@OBJEXT@ runtestspp@EXEEXT@ runtestspp.@OBJEXT@ + cd tests && rm -f chardata.@OBJEXT@ memcheck.@OBJEXT@ minicheck.@OBJEXT@ rm -rf .libs libexpat.la rm -f examples/core tests/core xmlwf/core @@ -73,9 +73,9 @@ extraclean: distclean rm -f aclocal.m4 m4/* rm -f conftools/ltmain.sh conftools/install-sh conftools/config.guess conftools/config.sub -check: tests/runtests tests/runtestspp - tests/runtests - tests/runtestspp +check: tests/runtests@EXEEXT@ tests/runtestspp@EXEEXT@ + ./run.sh tests/runtests@EXEEXT@ + ./run.sh tests/runtestspp@EXEEXT@ $(MANFILE): $(MAKE) -C doc xmlwf.1 @@ -124,7 +124,7 @@ LTFLAGS = --verbose COMPILE = $(CC) $(INCLUDES) $(CFLAGS) $(DEFS) $(CPPFLAGS) CXXCOMPILE = $(CXX) $(INCLUDES) $(CXXFLAGS) $(DEFS) $(CPPFLAGS) LTCOMPILE = $(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE) -LINK_LIB = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -no-undefined $(VSNFLAG) -rpath $(libdir) $(LDFLAGS) -o $@ +LINK_LIB = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -no-undefined $(VSNFLAG) -rpath $(libdir) $(LDFLAGS) @LIBS@ -o $@ LINK_EXE = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) $(LDFLAGS) -o $@ LINK_CXX_EXE = $(LIBTOOL) $(LTFLAGS) --mode=link $(CXXCOMPILE) $(LDFLAGS) -o $@ @@ -135,7 +135,7 @@ $(LIBRARY): $(LIB_OBJS) expat.pc: $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status $@ -lib/xmlparse.lo: lib/xmlparse.c lib/expat.h lib/xmlrole.h lib/xmltok.h \ +lib/xmlparse.lo: lib/xmlparse.c lib/expat.h lib/siphash.h lib/xmlrole.h lib/xmltok.h \ $(top_builddir)/expat_config.h lib/expat_external.h lib/internal.h lib/xmlrole.lo: lib/xmlrole.c lib/ascii.h lib/xmlrole.h \ @@ -151,7 +151,7 @@ XMLWF_OBJS = xmlwf/xmlwf.@OBJEXT@ xmlwf/xmlfile.@OBJEXT@ xmlwf/codepage.@OBJEXT@ xmlwf/xmlwf.@OBJEXT@: xmlwf/xmlwf.c xmlwf/xmlfile.@OBJEXT@: xmlwf/xmlfile.c xmlwf/codepage.@OBJEXT@: xmlwf/codepage.c -xmlwf/@FILEMAP@.@OBJEXT@: xmlwf/@FILEMAP@.c +xmlwf/@FILEMAP@.@OBJEXT@: xmlwf/@FILEMAP@.c xmlwf/filemap.h xmlwf/xmlwf@EXEEXT@: $(XMLWF_OBJS) $(LIBRARY) $(LINK_EXE) $(XMLWF_OBJS) $(LIBRARY) @@ -165,12 +165,13 @@ examples/outline: examples/outline.@OBJEXT@ $(LIBRARY) tests/chardata.@OBJEXT@: tests/chardata.c tests/chardata.h tests/minicheck.@OBJEXT@: tests/minicheck.c tests/minicheck.h -tests/runtests.@OBJEXT@: tests/runtests.c tests/chardata.h -tests/runtests: tests/runtests.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) - $(LINK_EXE) tests/runtests.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) -tests/runtestspp.@OBJEXT@: tests/runtestspp.cpp tests/runtests.c tests/chardata.h -tests/runtestspp: tests/runtestspp.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) - $(LINK_CXX_EXE) tests/runtestspp.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ $(LIBRARY) +tests/memcheck.@OBJEXT@: tests/memcheck.c tests/memcheck.h +tests/runtests.@OBJEXT@: tests/runtests.c tests/chardata.h tests/memcheck.h lib/siphash.h +tests/runtests@EXEEXT@: tests/runtests.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ tests/memcheck.@OBJEXT@ $(LIBRARY) + $(LINK_EXE) tests/runtests.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ tests/memcheck.@OBJEXT@ $(LIBRARY) +tests/runtestspp.@OBJEXT@: tests/runtestspp.cpp tests/runtests.c tests/chardata.h tests/memcheck.h +tests/runtestspp@EXEEXT@: tests/runtestspp.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ tests/memcheck.@OBJEXT@ $(LIBRARY) + $(LINK_CXX_EXE) tests/runtestspp.@OBJEXT@ tests/chardata.@OBJEXT@ tests/minicheck.@OBJEXT@ tests/memcheck.@OBJEXT@ $(LIBRARY) tests/benchmark/benchmark.@OBJEXT@: tests/benchmark/benchmark.c tests/benchmark/benchmark: tests/benchmark/benchmark.@OBJEXT@ $(LIBRARY) @@ -181,14 +182,14 @@ run-benchmark: tests/benchmark/benchmark tests/xmlts.zip: wget --output-document=tests/xmlts.zip \ - http://www.w3.org/XML/Test/xmlts20080827.zip + https://www.w3.org/XML/Test/xmlts20080827.zip tests/xmlconf: tests/xmlts.zip cd tests && unzip -q xmlts.zip run-xmltest: xmlwf/xmlwf@EXEEXT@ tests/xmlconf - tests/xmltest.sh 2>&1 | tee tests/xmltest.log - diff -u tests/xmltest.log.expected tests/xmltest.log + tests/xmltest.sh "$(PWD)/run.sh $(PWD)/xmlwf/xmlwf@EXEEXT@" 2>&1 | tee tests/xmltest.log + diff -u -b tests/xmltest.log.expected tests/xmltest.log .PHONY: qa qa: diff --git a/modules/expat/README b/modules/expat/README index a7d28450..cd11a226 100644 --- a/modules/expat/README +++ b/modules/expat/README @@ -1,5 +1,5 @@ - Expat, Release 2.2.0 + Expat, Release 2.2.1 This is Expat, a C library for parsing XML, written by James Clark. Expat is a stream-oriented XML parser. This means that you register diff --git a/modules/expat/buildconf.sh b/modules/expat/buildconf.sh new file mode 100755 index 00000000..8eb0a76d --- /dev/null +++ b/modules/expat/buildconf.sh @@ -0,0 +1,30 @@ +#! /bin/sh + +#-------------------------------------------------------------------------- +# autoconf 2.58 or newer +# +ac_version="`${AUTOCONF:-autoconf} --version 2> /dev/null | head -1 | sed -e 's/^[^0-9]*//' -e 's/[a-z]* *$//'`" +if test -z "$ac_version"; then + echo "ERROR: autoconf not found." + echo " You need autoconf version 2.58 or newer installed." + exit 1 +fi +IFS=.; set $ac_version; IFS=' ' +if test "$1" = "2" -a "$2" -lt "58" || test "$1" -lt "2"; then + echo "ERROR: autoconf version $ac_version found." + echo " You need autoconf version 2.58 or newer installed." + exit 1 +fi + +echo "Creating configure ..." +${AUTORECONF:-autoreconf} -fvi + +echo "Creating conftools/install-sh ..." +# .. for configure, despite not using automake +automake --add-missing 2>/dev/null || true + +# toss this; it gets created by autoconf on some systems +rm -rf autom4te*.cache + +# exit with the right value, so any calling script can continue +exit 0 diff --git a/modules/expat/configure.ac b/modules/expat/configure.ac index a06c3e49..444c0026 100644 --- a/modules/expat/configure.ac +++ b/modules/expat/configure.ac @@ -46,7 +46,7 @@ dnl If the API changes incompatibly set LIBAGE back to 0 dnl LIBCURRENT=7 # sync -LIBREVISION=2 # with +LIBREVISION=3 # with LIBAGE=6 # CMakeLists.txt! AC_CONFIG_HEADER(expat_config.h) @@ -80,6 +80,10 @@ if test "$GCC" = yes ; then if test "x$CXXFLAGS" = x ; then CXXFLAGS=`echo "$CFLAGS" | sed 's/ -Wmissing-prototypes -Wstrict-prototypes//'` fi + + CFLAGS="${CFLAGS} -fno-strict-aliasing" + CXXFLAGS="${CXXFLAGS} -fno-strict-aliasing" + LDFLAGS="${LDFLAGS} -fno-strict-aliasing" fi dnl Checks for header files. @@ -95,6 +99,69 @@ AC_C_CONST AC_TYPE_SIZE_T AC_CHECK_FUNCS(memmove bcopy) + +AC_ARG_WITH([libbsd], [ +AS_HELP_STRING([--with-libbsd], [utilize libbsd (for arc4random_buf)]) +], [], [with_libbsd=no]) +AS_IF([test "x${with_libbsd}" != xno], [ + AC_CHECK_LIB([bsd], [arc4random_buf], [], [ + AS_IF([test "x${with_libbsd}" = xyes], [ + AC_MSG_ERROR([Enforced use of libbsd cannot be satisfied.]) + ]) + ]) +]) +AC_MSG_CHECKING([for arc4random_buf (BSD or libbsd)]) +AC_LINK_IFELSE([AC_LANG_SOURCE([ + #include /* for arc4random_buf on BSD, for NULL */ + #if defined(HAVE_LIBBSD) + # include + #endif + int main() { + arc4random_buf(NULL, 0U); + return 0; + } +])], [ + AC_DEFINE([HAVE_ARC4RANDOM_BUF], [1], + [Define to 1 if you have the `arc4random_buf' function.]) + AC_MSG_RESULT([yes]) +], [ + AC_MSG_RESULT([no]) +]) + + +AC_MSG_CHECKING([for getrandom (Linux 3.17+, glibc 2.25+)]) +AC_LINK_IFELSE([AC_LANG_SOURCE([ + #include /* for NULL */ + #include + int main() { + return getrandom(NULL, 0U, 0U); + } +])], [ + AC_DEFINE([HAVE_GETRANDOM], [1], + [Define to 1 if you have the `getrandom' function.]) + AC_MSG_RESULT([yes]) +], [ + AC_MSG_RESULT([no]) + + AC_MSG_CHECKING([for syscall SYS_getrandom (Linux 3.17+)]) + AC_LINK_IFELSE([AC_LANG_SOURCE([ + #include /* for NULL */ + #include /* for syscall */ + #include /* for SYS_getrandom */ + int main() { + syscall(SYS_getrandom, NULL, 0, 0); + return 0; + } + ])], [ + AC_DEFINE([HAVE_SYSCALL_GETRANDOM], [1], + [Define to 1 if you have `syscall' and `SYS_getrandom'.]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) + + dnl Only needed for xmlwf: AC_CHECK_HEADERS(fcntl.h unistd.h) AC_TYPE_OFF_T @@ -119,10 +186,10 @@ AC_DEFUN([AC_CPP_FUNC], [AC_REQUIRE([AC_PROG_CC_STDC])dnl AC_CACHE_CHECK([for an ANSI C99-conforming __func__], ac_cv_cpp_func, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], -[[char *foo = __func__;]])], +[[const char *foo = __func__;]])], [ac_cv_cpp_func=yes], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], -[[char *foo = __FUNCTION__;]])], +[[const char *foo = __FUNCTION__;]])], [ac_cv_cpp_func=__FUNCTION__], [ac_cv_cpp_func=no])])]) if test $ac_cv_cpp_func = __FUNCTION__; then @@ -144,10 +211,25 @@ AC_DEFINE([XML_NS], 1, [Define to make XML Namespaces functionality available.]) AC_DEFINE([XML_DTD], 1, [Define to make parameter entity parsing functionality available.]) -AC_DEFINE([XML_CONTEXT_BYTES], 1024, - [Define to specify how much context to retain around the current parse point.]) + +AC_ARG_ENABLE([xml-context], + AS_HELP_STRING([--enable-xml-context @<:@COUNT@:>@], + [Retain context around the current parse point; + default is enabled and a size of 1024 bytes]) +AS_HELP_STRING([--disable-xml-context], + [Do not retain context around the current parse point]), + [enable_xml_context=${enableval}]) +AS_IF([test "x${enable_xml_context}" != "xno"], [ + AS_IF([test "x${enable_xml_context}" = "xyes" \ + -o "x${enable_xml_context}" = "x"], [ + enable_xml_context=1024 + ]) + AC_DEFINE_UNQUOTED([XML_CONTEXT_BYTES], [${enable_xml_context}], + [Define to specify how much context to retain around the current parse point.]) +]) AC_CONFIG_FILES([Makefile expat.pc]) +AC_CONFIG_FILES([run.sh], [chmod +x run.sh]) AC_OUTPUT abs_srcdir="`cd $srcdir && pwd`" diff --git a/modules/expat/conftools/.gitignore b/modules/expat/conftools/.gitignore new file mode 100644 index 00000000..43c4c8e1 --- /dev/null +++ b/modules/expat/conftools/.gitignore @@ -0,0 +1,6 @@ +config.guess +config.sub +install-sh +libtool.m4 +ltconfig +ltmain.sh diff --git a/modules/expat/coverage.sh b/modules/expat/coverage.sh new file mode 100755 index 00000000..10a0a20d --- /dev/null +++ b/modules/expat/coverage.sh @@ -0,0 +1,211 @@ +#! /bin/bash +# Copyright (C) Sebastian Pipping +# Licensed under the MIT license + +export PS4='# ' + + +_get_source_dir() { + echo "source__${version}" +} + + +_get_build_dir() { + local libbsd_part= + if ${with_libbsd}; then + libbsd_part=__libbsd + fi + + local mingw_part= + if ${with_mingw}; then + mingw_part=__windows + fi + + echo "build__${version}__unicode_${unicode_enabled}__xml_context_${xml_context}${libbsd_part}${mingw_part}" +} + + +_get_coverage_dir() { + echo "coverage__${version}" +} + + +_configure() { + local configure_args=() + + ${unicode_enabled} \ + && configure_args+=( CPPFLAGS='-DXML_UNICODE -DXML_UNICODE_WCHAR_T' ) + + if [[ ${xml_context} -eq 0 ]]; then + configure_args+=( --disable-xml-context ) + else + configure_args+=( --enable-xml-context=${xml_context} ) + fi + + ${with_libbsd} && configure_args+=( --with-libbsd ) + ${with_mingw} && configure_args+=( --host=i686-w64-mingw32 ) + + ( + set -x + ./buildconf.sh &> configure.log + ./configure "${configure_args[@]}" "$@" &>> configure.log + ) +} + + +_copy_to() { + local target_dir="$1" + [[ -d "${target_dir}" ]] && return 0 + + mkdir "${target_dir}" + git archive --format=tar "${version}" | ( cd "${target_dir}" && tar x ) +} + + +_copy_missing_mingw_libaries() { + # These extra files are copied because + # * coverage GCC fflags make them needed + # * With WINEDLLPATH Wine look for .dll.so in these folders, not .dll + local target="$1" + local mingw_dll_dir="$(dirname "$(ls -1 /usr/lib*/gcc/i686-w64-mingw32/*/libgcc_s_sjlj-1.dll | head -n1)")" + for dll in libgcc_s_sjlj-1.dll libstdc++-6.dll; do + ( + set -x + ln -s "${mingw_dll_dir}"/${dll} "${target}"/${dll} + ) + done +} + + +_run() { + local source_dir="$1" + local build_dir="$2" + local capture_dir=lib + + local BASE_FLAGS='-pipe -Wall -Wextra -pedantic -Wno-overlength-strings' + BASE_FLAGS+=' --coverage --no-inline' + + local CFLAGS="-std=c89 ${BASE_FLAGS}" + local CXXFLAGS="-std=c++98 ${BASE_FLAGS}" + + ( + set -e + cd "${build_dir}" + + _configure \ + CFLAGS="${BASE_FLAGS}" \ + CXXFLAGS="${BASE_FLAGS}" + + ( + set -x + make buildlib &> build.log + + lcov -c -d "${capture_dir}" -i -o "${coverage_info}-zero" &> run.log + ) + + if ${with_mingw}; then + _copy_missing_mingw_libaries .libs + fi + + set -x + make check run-xmltest + + lcov -c -d "${capture_dir}" -o "${coverage_info}-test" &>> run.log + lcov \ + -a "${coverage_info}-zero" \ + -a "${coverage_info}-test" \ + -o "${coverage_info}-all" \ + &>> run.log + + # Make sure that files overlap in report despite different build folders + sed "/SF:/ s,${build_dir}/,${source_dir}/," "${coverage_info}-all" > "${coverage_info}" + ) |& sed 's,^, ,' + res=${PIPESTATUS[0]} + + if [[ ${res} -eq 0 ]]; then + echo PASSED + else + echo FAILED >&2 + return 1 + fi +} + + +_merge_coverage_info() { + local coverage_dir="$1" + shift + local build_dirs=( "$@" ) + + mkdir -p "${coverage_dir}" + ( + local lcov_merge_args=() + for build_dir in "${build_dirs[@]}"; do + lcov_merge_args+=( -a "${build_dir}/${coverage_info}" ) + done + lcov_merge_args+=( -o "${coverage_dir}/${coverage_info}" ) + + set -x + lcov "${lcov_merge_args[@]}" + ) &> "${coverage_dir}/merge.log" +} + + +_render_html_report() { + local coverage_dir="$1" + genhtml -o "${coverage_dir}" "${coverage_dir}/${coverage_info}" &> "${coverage_dir}/render.log" +} + + +_show_summary() { + local coverage_dir="$1" + lcov -q -l "${coverage_dir}/${coverage_info}" | grep -v '^\[' +} + + +_main() { + version="$(git describe --tags)" + coverage_info=coverage.info + + local build_dirs=() + local source_dir="$(_get_source_dir)" + local coverage_dir="$(_get_coverage_dir)" + + _copy_to "${source_dir}" + + _build_case() { + local build_dir="$(_get_build_dir)" + + echo "[${build_dir}]" + _copy_to "${build_dir}" + _run "${source_dir}" "${build_dir}" + + build_dirs+=( "${build_dir}" ) + } + + # All combinations: + with_libbsd=false + for with_mingw in true false ; do + for unicode_enabled in false ; do + for xml_context in 0 1024 ; do + _build_case + done + done + done + + # Single cases: + with_libbsd=true _build_case + + echo + echo 'Merging coverage files...' + _merge_coverage_info "${coverage_dir}" "${build_dirs[@]}" + + echo 'Rendering HTML report...' + _render_html_report "${coverage_dir}" + echo "--> ${coverage_dir}/index.html" + + echo + _show_summary "${coverage_dir}" +} + + +_main diff --git a/modules/expat/doc/.gitignore b/modules/expat/doc/.gitignore new file mode 100644 index 00000000..65c1472d --- /dev/null +++ b/modules/expat/doc/.gitignore @@ -0,0 +1,2 @@ +/XMLWF.1 +/xmlwf.1 diff --git a/modules/expat/doc/reference.html b/modules/expat/doc/reference.html index a4ab4053..350b9b67 100644 --- a/modules/expat/doc/reference.html +++ b/modules/expat/doc/reference.html @@ -277,7 +277,7 @@

Building under Win32

If you're using the GNU compiler under cygwin, follow the Unix directions in the next section. Otherwise if you have Microsoft's Developer Studio installed, then from Windows Explorer double-click on -"expat.dsp" in the lib directory and build and install in the usual +"expat.vcxproj" in the lib directory and build and install in the usual manner.

Alternatively, you may download the Win32 binary package that diff --git a/modules/expat/examples/.gitignore b/modules/expat/examples/.gitignore new file mode 100644 index 00000000..88a46969 --- /dev/null +++ b/modules/expat/examples/.gitignore @@ -0,0 +1,8 @@ +Makefile +elements +elements.plg +outline +outline.plg +Debug +Release +.libs diff --git a/modules/expat/examples/elements.c b/modules/expat/examples/elements.c index 0ca1abd9..fe1699c5 100644 --- a/modules/expat/examples/elements.c +++ b/modules/expat/examples/elements.c @@ -6,11 +6,7 @@ */ #include -#include "expat.h" - -#if defined(__amigaos__) && defined(__USE_INLINE__) -#include -#endif +#include #ifdef XML_LARGE_SIZE #if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400 diff --git a/modules/expat/examples/elements.vcxproj b/modules/expat/examples/elements.vcxproj new file mode 100644 index 00000000..20da9b2c --- /dev/null +++ b/modules/expat/examples/elements.vcxproj @@ -0,0 +1,139 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + {35262250-C85F-463A-9F6D-670088BFA17E} + + + + Application + v120 + false + MultiByte + + + Application + v120 + false + MultiByte + + + + + + + + + + + + + + + .\..\win32\bin\Release\ + .\..\win32\tmp\Release-elements\ + false + + + .\..\win32\bin\Debug\ + .\..\win32\tmp\Debug-elements\ + true + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + false + ..\lib;%(AdditionalIncludeDirectories) + NDEBUG;_CONSOLE;XML_STATIC;%(PreprocessorDefinitions) + .\..\win32\tmp\Release-elements\ + .\..\win32\tmp\Release-elements\elements.pch + .\..\win32\tmp\Release-elements\ + .\..\win32\tmp\Release-elements\ + + + .\..\win32\bin\Release\elements.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Release\elements.bsc + + + true + Console + ..\win32\bin\Release\elements.exe + ..\win32\bin\Release;%(AdditionalLibraryDirectories) + libexpatMT.lib;%(AdditionalDependencies) + + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + EditAndContinue + ..\lib;%(AdditionalIncludeDirectories) + _DEBUG;_CONSOLE;XML_STATIC;%(PreprocessorDefinitions) + .\..\win32\tmp\Debug-elements\ + true + .\..\win32\tmp\Debug-elements\elements.pch + .\..\win32\tmp\Debug-elements\ + .\..\win32\tmp\Debug-elements\ + EnableFastChecks + + + .\..\win32\bin\Debug\elements.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Debug\elements.bsc + + + true + true + Console + ..\win32\bin\Debug\elements.exe + ..\win32\bin\Debug;%(AdditionalLibraryDirectories) + libexpatMT.lib;%(AdditionalDependencies) + + + + + + + + {58a821bc-e4af-4df4-9a54-2baa22b92615} + false + + + + + + \ No newline at end of file diff --git a/modules/expat/examples/elements.vcxproj.filters b/modules/expat/examples/elements.vcxproj.filters new file mode 100644 index 00000000..ab374c18 --- /dev/null +++ b/modules/expat/examples/elements.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {95d10a62-f554-4b10-a08b-cc74ba9fe102} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {21ef9308-545b-4d8d-8bde-012f925efa3a} + h;hpp;hxx;hm;inl + + + {ddac4f51-12d6-4e8f-817c-12c85eb1ffd2} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/modules/expat/examples/outline.c b/modules/expat/examples/outline.c index d9b09176..2d1e63c3 100644 --- a/modules/expat/examples/outline.c +++ b/modules/expat/examples/outline.c @@ -25,10 +25,6 @@ #include #include -#if defined(__amigaos__) && defined(__USE_INLINE__) -#include -#endif - #ifdef XML_LARGE_SIZE #if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400 #define XML_FMT_INT_MOD "I64" diff --git a/modules/expat/examples/outline.vcxproj b/modules/expat/examples/outline.vcxproj new file mode 100644 index 00000000..56a065f7 --- /dev/null +++ b/modules/expat/examples/outline.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + {DE74E6FD-E107-4326-B1B0-A0CFEEB64F25} + + + + Application + v120 + + + Application + v120 + false + MultiByte + + + Application + v120 + false + MultiByte + + + + + + + + + + + + + + + + + + .\..\win32\bin\Debug\ + .\..\win32\tmp\Debug-outline\ + true + + + .\..\win32\bin\Release\ + .\..\win32\tmp\Release-outline\ + false + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + true + EditAndContinue + ..\lib;%(AdditionalIncludeDirectories) + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\..\win32\tmp\Debug-outline\ + .\..\win32\tmp\Debug-outline\outline.pch + .\..\win32\tmp\Debug-outline\ + .\..\win32\tmp\Debug-outline\ + EnableFastChecks + + + .\..\win32\bin\Debug\outline.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Debug\outline.bsc + + + true + true + Console + ..\win32\bin\Debug\outline.exe + ..\win32\bin\Debug;%(AdditionalLibraryDirectories) + libexpat.lib;%(AdditionalDependencies) + + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + false + ..\lib;%(AdditionalIncludeDirectories) + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\..\win32\tmp\Release-outline\ + .\..\win32\tmp\Release-outline\outline.pch + .\..\win32\tmp\Release-outline\ + .\..\win32\tmp\Release-outline\ + + + .\..\win32\bin\Release\outline.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Release\outline.bsc + + + true + Console + ..\win32\bin\Release\outline.exe + ..\win32\bin\Release;%(AdditionalLibraryDirectories) + libexpat.lib;%(AdditionalDependencies) + + + + + + + + {45a5074d-66e8-44a4-a03f-018027b528d6} + false + + + + + + \ No newline at end of file diff --git a/modules/expat/examples/outline.vcxproj.filters b/modules/expat/examples/outline.vcxproj.filters new file mode 100644 index 00000000..0c23f352 --- /dev/null +++ b/modules/expat/examples/outline.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {48092a1f-486d-4bd8-a9ea-d087423ab371} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {d9494f7e-987c-467b-a3e0-ea577aea229d} + h;hpp;hxx;hm;inl + + + {7e3cfca9-158f-4e78-be6c-02d599fd9254} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/modules/expat/expat.sln b/modules/expat/expat.sln new file mode 100644 index 00000000..d1c4efc2 --- /dev/null +++ b/modules/expat/expat.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "elements", "examples\elements.vcxproj", "{35262250-C85F-463A-9F6D-670088BFA17E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "expat", "lib\expat.vcxproj", "{45A5074D-66E8-44A4-A03F-018027B528D6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "expat_static", "lib\expat_static.vcxproj", "{58A821BC-E4AF-4DF4-9A54-2BAA22B92615}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "expatw", "lib\expatw.vcxproj", "{C04F1C11-7079-48AD-A90B-6F59B7A55BEF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "expatw_static", "lib\expatw_static.vcxproj", "{9220B0F2-C895-4CB2-91D1-1C16C4ECB759}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "outline", "examples\outline.vcxproj", "{DE74E6FD-E107-4326-B1B0-A0CFEEB64F25}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xmlwf", "xmlwf\xmlwf.vcxproj", "{E3C5991F-5238-4168-A179-275D1AC98D7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Template|Win32 = Template|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {35262250-C85F-463A-9F6D-670088BFA17E}.Debug|Win32.ActiveCfg = Debug|Win32 + {35262250-C85F-463A-9F6D-670088BFA17E}.Debug|Win32.Build.0 = Debug|Win32 + {35262250-C85F-463A-9F6D-670088BFA17E}.Release|Win32.ActiveCfg = Release|Win32 + {35262250-C85F-463A-9F6D-670088BFA17E}.Release|Win32.Build.0 = Release|Win32 + {35262250-C85F-463A-9F6D-670088BFA17E}.Template|Win32.ActiveCfg = Release|Win32 + {35262250-C85F-463A-9F6D-670088BFA17E}.Template|Win32.Build.0 = Release|Win32 + {45A5074D-66E8-44A4-A03F-018027B528D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {45A5074D-66E8-44A4-A03F-018027B528D6}.Debug|Win32.Build.0 = Debug|Win32 + {45A5074D-66E8-44A4-A03F-018027B528D6}.Release|Win32.ActiveCfg = Release|Win32 + {45A5074D-66E8-44A4-A03F-018027B528D6}.Release|Win32.Build.0 = Release|Win32 + {45A5074D-66E8-44A4-A03F-018027B528D6}.Template|Win32.ActiveCfg = Template|Win32 + {45A5074D-66E8-44A4-A03F-018027B528D6}.Template|Win32.Build.0 = Template|Win32 + {58A821BC-E4AF-4DF4-9A54-2BAA22B92615}.Debug|Win32.ActiveCfg = Debug|Win32 + {58A821BC-E4AF-4DF4-9A54-2BAA22B92615}.Debug|Win32.Build.0 = Debug|Win32 + {58A821BC-E4AF-4DF4-9A54-2BAA22B92615}.Release|Win32.ActiveCfg = Release|Win32 + {58A821BC-E4AF-4DF4-9A54-2BAA22B92615}.Release|Win32.Build.0 = Release|Win32 + {58A821BC-E4AF-4DF4-9A54-2BAA22B92615}.Template|Win32.ActiveCfg = Template|Win32 + {58A821BC-E4AF-4DF4-9A54-2BAA22B92615}.Template|Win32.Build.0 = Template|Win32 + {C04F1C11-7079-48AD-A90B-6F59B7A55BEF}.Debug|Win32.ActiveCfg = Debug|Win32 + {C04F1C11-7079-48AD-A90B-6F59B7A55BEF}.Debug|Win32.Build.0 = Debug|Win32 + {C04F1C11-7079-48AD-A90B-6F59B7A55BEF}.Release|Win32.ActiveCfg = Release|Win32 + {C04F1C11-7079-48AD-A90B-6F59B7A55BEF}.Release|Win32.Build.0 = Release|Win32 + {C04F1C11-7079-48AD-A90B-6F59B7A55BEF}.Template|Win32.ActiveCfg = Template|Win32 + {C04F1C11-7079-48AD-A90B-6F59B7A55BEF}.Template|Win32.Build.0 = Template|Win32 + {9220B0F2-C895-4CB2-91D1-1C16C4ECB759}.Debug|Win32.ActiveCfg = Debug|Win32 + {9220B0F2-C895-4CB2-91D1-1C16C4ECB759}.Debug|Win32.Build.0 = Debug|Win32 + {9220B0F2-C895-4CB2-91D1-1C16C4ECB759}.Release|Win32.ActiveCfg = Release|Win32 + {9220B0F2-C895-4CB2-91D1-1C16C4ECB759}.Release|Win32.Build.0 = Release|Win32 + {9220B0F2-C895-4CB2-91D1-1C16C4ECB759}.Template|Win32.ActiveCfg = Template|Win32 + {9220B0F2-C895-4CB2-91D1-1C16C4ECB759}.Template|Win32.Build.0 = Template|Win32 + {DE74E6FD-E107-4326-B1B0-A0CFEEB64F25}.Debug|Win32.ActiveCfg = Debug|Win32 + {DE74E6FD-E107-4326-B1B0-A0CFEEB64F25}.Debug|Win32.Build.0 = Debug|Win32 + {DE74E6FD-E107-4326-B1B0-A0CFEEB64F25}.Release|Win32.ActiveCfg = Release|Win32 + {DE74E6FD-E107-4326-B1B0-A0CFEEB64F25}.Release|Win32.Build.0 = Release|Win32 + {DE74E6FD-E107-4326-B1B0-A0CFEEB64F25}.Template|Win32.ActiveCfg = Template|Win32 + {DE74E6FD-E107-4326-B1B0-A0CFEEB64F25}.Template|Win32.Build.0 = Template|Win32 + {E3C5991F-5238-4168-A179-275D1AC98D7E}.Debug|Win32.ActiveCfg = Debug|Win32 + {E3C5991F-5238-4168-A179-275D1AC98D7E}.Debug|Win32.Build.0 = Debug|Win32 + {E3C5991F-5238-4168-A179-275D1AC98D7E}.Release|Win32.ActiveCfg = Release|Win32 + {E3C5991F-5238-4168-A179-275D1AC98D7E}.Release|Win32.Build.0 = Release|Win32 + {E3C5991F-5238-4168-A179-275D1AC98D7E}.Template|Win32.ActiveCfg = Template|Win32 + {E3C5991F-5238-4168-A179-275D1AC98D7E}.Template|Win32.Build.0 = Template|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/modules/expat/expat.spec b/modules/expat/expat.spec new file mode 100644 index 00000000..c852f649 --- /dev/null +++ b/modules/expat/expat.spec @@ -0,0 +1,113 @@ +%define version 2.2.1 +%define release 1 + +Summary: Expat is an XML 1.0 parser written in C. +Name: expat +Version: %{version} +Release: %{release} +License: MIT/X +Group: Utilities/parsers +URL: http://www.libexpat.org/ +Source: http://download.sourceforge.net/expat/expat-%{version}.tar.gz +BuildRoot: /var/tmp/%{name}-buildroot + +%description +Expat is an XML 1.0 parser written in C by James Clark. It aims to be +fully conforming. It is not a validating XML parser. + +%prep +%setup + +%build +./configure +make lib xmlwf + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/usr/bin +mkdir -p $RPM_BUILD_ROOT/usr/lib +mkdir -p $RPM_BUILD_ROOT/usr/include +make install DESTDIR=$RPM_BUILD_ROOT prefix=/usr +install -D xmlwf/xmlwf $RPM_BUILD_ROOT/usr/bin/xmlwf + +%files +%doc COPYING Changes MANIFEST README doc/reference.html doc/style.css doc/*.png +/usr/bin/xmlwf +/usr/lib +/usr/include/expat.h +/usr/include/expat_config.h +/usr/include/expat_external.h +/usr/share/man/man1/xmlwf.1.gz + +%changelog +* Sat Jun 17 2017 Sebastian Pipping +[Release 2.2.1-1] +- Update for the 2.2.1 release. + +* Tue Jun 21 2016 Sebastian Pipping +[Release 2.2.0-1] +- Update for the 2.2.0 release. + +* Wed Mar 2 2016 Sebastian Pipping +[Release 2.1.1-1] +- Update for the 2.1.1 release. + +* Sat Mar 3 2012 Karl Waclawek +[Release 2.1.0-1] +- Update for the 2.1.0 release. + +* Sun Nov 26 2006 Karl Waclawek +[Release 2.0.1-1] +- Update for the 2.0.1 release. + +* Fri Jul 16 2004 Fred L. Drake, Jr. +[Release 1.95.8-1] +- Update for the 1.95.8 release. +- Add the expat_external.h header to the installed files. + +* Tue Oct 21 2003 Fred L. Drake, Jr. +- Update list of documentation files; we missed a .png file in the + previous release. + +* Mon Oct 20 2003 Fred L. Drake, Jr. +[Release 1.95.7-1] +- Updated for the 1.95.7 release. + +* Sat Jan 25 2003 Fred L. Drake, Jr. +[Release 1.95.6-1] +- Updated for the 1.95.6 release. + +* Wed Sep 4 2002 Fred L. Drake, Jr. +[Release 1.95.5-1] +- Updated for the 1.95.5 release. +- Updated URL for Expat home page to point to www.libexpat.org. +- Added "Valid XHTML 1.0" icon to the installed documentation. + +* Sat Jun 29 2002 Fred L. Drake, Jr. +[Release 1.95.4-1] +- Updated for the 1.95.4 release. + +* Fri May 17 2002 Fred L. Drake, Jr. +[Release 1.95.3-1] +- Updated for the 1.95.3 release. +- Added xmlwf man page to the list of files. + +* Wed Jul 25 2001 Fred L. Drake, Jr. +[Release 1.95.2-1] +- Updated for the 1.95.2 release. + +* Sun Feb 18 2001 Sean Reifschneider +[Release 1.95.1-1tummy] +- Updated to 1.95.1 release. +- Removed the "/usr/include/expat" directory for headers, as it now uses + "expat.h" instead of "xmlparser.h". + +* Thu Jan 25 2001 Sean Reifschneider +[Release 1.1-3tummy] +- Moved xmlparse.h into "/usr/include/expat" directory to prevent conflict + with w3c-libwww-devel package. + +* Wed Sep 6 2000 Sean Reifschneider +- Modified to install into /usr. +- Modified to use RPM_BUILD_ROOT instead of writing directly to install + location. diff --git a/modules/expat/gennmtab/.gitignore b/modules/expat/gennmtab/.gitignore new file mode 100755 index 00000000..f966c45c --- /dev/null +++ b/modules/expat/gennmtab/.gitignore @@ -0,0 +1,3 @@ +Debug +Release +gennmtab.plg diff --git a/modules/expat/gennmtab/gennmtab.c b/modules/expat/gennmtab/gennmtab.c new file mode 100644 index 00000000..8a4ff347 --- /dev/null +++ b/modules/expat/gennmtab/gennmtab.c @@ -0,0 +1,429 @@ +/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd + See the file COPYING for copying permission. +*/ + +#include +#include +#include + +struct range { + int start; + int end; +}; + +struct range nmstrt[] = { + { '_' }, + { ':' }, + /* BaseChar */ + { 0x0041, 0x005a }, + { 0x0061, 0x007a }, + { 0x00c0, 0x00d6 }, + { 0x00d8, 0x00f6 }, + { 0x00f8, 0x00ff }, + { 0x0100, 0x0131 }, + { 0x0134, 0x013e }, + { 0x0141, 0x0148 }, + { 0x014a, 0x017e }, + { 0x0180, 0x01c3 }, + { 0x01cd, 0x01f0 }, + { 0x01f4, 0x01f5 }, + { 0x01fa, 0x0217 }, + { 0x0250, 0x02a8 }, + { 0x02bb, 0x02c1 }, + { 0x0386 }, + { 0x0388, 0x038a }, + { 0x038c }, + { 0x038e, 0x03a1 }, + { 0x03a3, 0x03ce }, + { 0x03d0, 0x03d6 }, + { 0x03da }, + { 0x03dc }, + { 0x03de }, + { 0x03e0 }, + { 0x03e2, 0x03f3 }, + { 0x0401, 0x040c }, + { 0x040e, 0x044f }, + { 0x0451, 0x045c }, + { 0x045e, 0x0481 }, + { 0x0490, 0x04c4 }, + { 0x04c7, 0x04c8 }, + { 0x04cb, 0x04cc }, + { 0x04d0, 0x04eb }, + { 0x04ee, 0x04f5 }, + { 0x04f8, 0x04f9 }, + { 0x0531, 0x0556 }, + { 0x0559 }, + { 0x0561, 0x0586 }, + { 0x05d0, 0x05ea }, + { 0x05f0, 0x05f2 }, + { 0x0621, 0x063a }, + { 0x0641, 0x064a }, + { 0x0671, 0x06b7 }, + { 0x06ba, 0x06be }, + { 0x06c0, 0x06ce }, + { 0x06d0, 0x06d3 }, + { 0x06d5 }, + { 0x06e5, 0x06e6 }, + { 0x0905, 0x0939 }, + { 0x093d }, + { 0x0958, 0x0961 }, + { 0x0985, 0x098c }, + { 0x098f, 0x0990 }, + { 0x0993, 0x09a8 }, + { 0x09aa, 0x09b0 }, + { 0x09b2 }, + { 0x09b6, 0x09b9 }, + { 0x09dc, 0x09dd }, + { 0x09df, 0x09e1 }, + { 0x09f0, 0x09f1 }, + { 0x0a05, 0x0a0a }, + { 0x0a0f, 0x0a10 }, + { 0x0a13, 0x0a28 }, + { 0x0a2a, 0x0a30 }, + { 0x0a32, 0x0a33 }, + { 0x0a35, 0x0a36 }, + { 0x0a38, 0x0a39 }, + { 0x0a59, 0x0a5c }, + { 0x0a5e }, + { 0x0a72, 0x0a74 }, + { 0x0a85, 0x0a8b }, + { 0x0a8d }, + { 0x0a8f, 0x0a91 }, + { 0x0a93, 0x0aa8 }, + { 0x0aaa, 0x0ab0 }, + { 0x0ab2, 0x0ab3 }, + { 0x0ab5, 0x0ab9 }, + { 0x0abd }, + { 0x0ae0 }, + { 0x0b05, 0x0b0c }, + { 0x0b0f, 0x0b10 }, + { 0x0b13, 0x0b28 }, + { 0x0b2a, 0x0b30 }, + { 0x0b32, 0x0b33 }, + { 0x0b36, 0x0b39 }, + { 0x0b3d }, + { 0x0b5c, 0x0b5d }, + { 0x0b5f, 0x0b61 }, + { 0x0b85, 0x0b8a }, + { 0x0b8e, 0x0b90 }, + { 0x0b92, 0x0b95 }, + { 0x0b99, 0x0b9a }, + { 0x0b9c }, + { 0x0b9e, 0x0b9f }, + { 0x0ba3, 0x0ba4 }, + { 0x0ba8, 0x0baa }, + { 0x0bae, 0x0bb5 }, + { 0x0bb7, 0x0bb9 }, + { 0x0c05, 0x0c0c }, + { 0x0c0e, 0x0c10 }, + { 0x0c12, 0x0c28 }, + { 0x0c2a, 0x0c33 }, + { 0x0c35, 0x0c39 }, + { 0x0c60, 0x0c61 }, + { 0x0c85, 0x0c8c }, + { 0x0c8e, 0x0c90 }, + { 0x0c92, 0x0ca8 }, + { 0x0caa, 0x0cb3 }, + { 0x0cb5, 0x0cb9 }, + { 0x0cde }, + { 0x0ce0, 0x0ce1 }, + { 0x0d05, 0x0d0c }, + { 0x0d0e, 0x0d10 }, + { 0x0d12, 0x0d28 }, + { 0x0d2a, 0x0d39 }, + { 0x0d60, 0x0d61 }, + { 0x0e01, 0x0e2e }, + { 0x0e30 }, + { 0x0e32, 0x0e33 }, + { 0x0e40, 0x0e45 }, + { 0x0e81, 0x0e82 }, + { 0x0e84 }, + { 0x0e87, 0x0e88 }, + { 0x0e8a }, + { 0x0e8d }, + { 0x0e94, 0x0e97 }, + { 0x0e99, 0x0e9f }, + { 0x0ea1, 0x0ea3 }, + { 0x0ea5 }, + { 0x0ea7 }, + { 0x0eaa, 0x0eab }, + { 0x0ead, 0x0eae }, + { 0x0eb0 }, + { 0x0eb2, 0x0eb3 }, + { 0x0ebd }, + { 0x0ec0, 0x0ec4 }, + { 0x0f40, 0x0f47 }, + { 0x0f49, 0x0f69 }, + { 0x10a0, 0x10c5 }, + { 0x10d0, 0x10f6 }, + { 0x1100 }, + { 0x1102, 0x1103 }, + { 0x1105, 0x1107 }, + { 0x1109 }, + { 0x110b, 0x110c }, + { 0x110e, 0x1112 }, + { 0x113c }, + { 0x113e }, + { 0x1140 }, + { 0x114c }, + { 0x114e }, + { 0x1150 }, + { 0x1154, 0x1155 }, + { 0x1159 }, + { 0x115f, 0x1161 }, + { 0x1163 }, + { 0x1165 }, + { 0x1167 }, + { 0x1169 }, + { 0x116d, 0x116e }, + { 0x1172, 0x1173 }, + { 0x1175 }, + { 0x119e }, + { 0x11a8 }, + { 0x11ab }, + { 0x11ae, 0x11af }, + { 0x11b7, 0x11b8 }, + { 0x11ba }, + { 0x11bc, 0x11c2 }, + { 0x11eb }, + { 0x11f0 }, + { 0x11f9 }, + { 0x1e00, 0x1e9b }, + { 0x1ea0, 0x1ef9 }, + { 0x1f00, 0x1f15 }, + { 0x1f18, 0x1f1d }, + { 0x1f20, 0x1f45 }, + { 0x1f48, 0x1f4d }, + { 0x1f50, 0x1f57 }, + { 0x1f59 }, + { 0x1f5b }, + { 0x1f5d }, + { 0x1f5f, 0x1f7d }, + { 0x1f80, 0x1fb4 }, + { 0x1fb6, 0x1fbc }, + { 0x1fbe }, + { 0x1fc2, 0x1fc4 }, + { 0x1fc6, 0x1fcc }, + { 0x1fd0, 0x1fd3 }, + { 0x1fd6, 0x1fdb }, + { 0x1fe0, 0x1fec }, + { 0x1ff2, 0x1ff4 }, + { 0x1ff6, 0x1ffc }, + { 0x2126 }, + { 0x212a, 0x212b }, + { 0x212e }, + { 0x2180, 0x2182 }, + { 0x3041, 0x3094 }, + { 0x30a1, 0x30fa }, + { 0x3105, 0x312c }, + { 0xac00, 0xd7a3 }, + /* Ideographic */ + { 0x4e00, 0x9fa5 }, + { 0x3007 }, + { 0x3021, 0x3029 }, +}; + +/* name chars that are not name start chars */ +struct range name[] = { + { '.' }, + { '-' }, + /* CombiningChar */ + { 0x0300, 0x0345 }, + { 0x0360, 0x0361 }, + { 0x0483, 0x0486 }, + { 0x0591, 0x05a1 }, + { 0x05a3, 0x05b9 }, + { 0x05bb, 0x05bd }, + { 0x05bf }, + { 0x05c1, 0x05c2 }, + { 0x05c4 }, + { 0x064b, 0x0652 }, + { 0x0670 }, + { 0x06d6, 0x06dc }, + { 0x06dd, 0x06df }, + { 0x06e0, 0x06e4 }, + { 0x06e7, 0x06e8 }, + { 0x06ea, 0x06ed }, + { 0x0901, 0x0903 }, + { 0x093c }, + { 0x093e, 0x094c }, + { 0x094d }, + { 0x0951, 0x0954 }, + { 0x0962, 0x0963 }, + { 0x0981, 0x0983 }, + { 0x09bc }, + { 0x09be }, + { 0x09bf }, + { 0x09c0, 0x09c4 }, + { 0x09c7, 0x09c8 }, + { 0x09cb, 0x09cd }, + { 0x09d7 }, + { 0x09e2, 0x09e3 }, + { 0x0a02 }, + { 0x0a3c }, + { 0x0a3e }, + { 0x0a3f }, + { 0x0a40, 0x0a42 }, + { 0x0a47, 0x0a48 }, + { 0x0a4b, 0x0a4d }, + { 0x0a70, 0x0a71 }, + { 0x0a81, 0x0a83 }, + { 0x0abc }, + { 0x0abe, 0x0ac5 }, + { 0x0ac7, 0x0ac9 }, + { 0x0acb, 0x0acd }, + { 0x0b01, 0x0b03 }, + { 0x0b3c }, + { 0x0b3e, 0x0b43 }, + { 0x0b47, 0x0b48 }, + { 0x0b4b, 0x0b4d }, + { 0x0b56, 0x0b57 }, + { 0x0b82, 0x0b83 }, + { 0x0bbe, 0x0bc2 }, + { 0x0bc6, 0x0bc8 }, + { 0x0bca, 0x0bcd }, + { 0x0bd7 }, + { 0x0c01, 0x0c03 }, + { 0x0c3e, 0x0c44 }, + { 0x0c46, 0x0c48 }, + { 0x0c4a, 0x0c4d }, + { 0x0c55, 0x0c56 }, + { 0x0c82, 0x0c83 }, + { 0x0cbe, 0x0cc4 }, + { 0x0cc6, 0x0cc8 }, + { 0x0cca, 0x0ccd }, + { 0x0cd5, 0x0cd6 }, + { 0x0d02, 0x0d03 }, + { 0x0d3e, 0x0d43 }, + { 0x0d46, 0x0d48 }, + { 0x0d4a, 0x0d4d }, + { 0x0d57 }, + { 0x0e31 }, + { 0x0e34, 0x0e3a }, + { 0x0e47, 0x0e4e }, + { 0x0eb1 }, + { 0x0eb4, 0x0eb9 }, + { 0x0ebb, 0x0ebc }, + { 0x0ec8, 0x0ecd }, + { 0x0f18, 0x0f19 }, + { 0x0f35 }, + { 0x0f37 }, + { 0x0f39 }, + { 0x0f3e }, + { 0x0f3f }, + { 0x0f71, 0x0f84 }, + { 0x0f86, 0x0f8b }, + { 0x0f90, 0x0f95 }, + { 0x0f97 }, + { 0x0f99, 0x0fad }, + { 0x0fb1, 0x0fb7 }, + { 0x0fb9 }, + { 0x20d0, 0x20dc }, + { 0x20e1 }, + { 0x302a, 0x302f }, + { 0x3099 }, + { 0x309a }, + /* Digit */ + { 0x0030, 0x0039 }, + { 0x0660, 0x0669 }, + { 0x06f0, 0x06f9 }, + { 0x0966, 0x096f }, + { 0x09e6, 0x09ef }, + { 0x0a66, 0x0a6f }, + { 0x0ae6, 0x0aef }, + { 0x0b66, 0x0b6f }, + { 0x0be7, 0x0bef }, + { 0x0c66, 0x0c6f }, + { 0x0ce6, 0x0cef }, + { 0x0d66, 0x0d6f }, + { 0x0e50, 0x0e59 }, + { 0x0ed0, 0x0ed9 }, + { 0x0f20, 0x0f29 }, + /* Extender */ + { 0xb7 }, + { 0x02d0 }, + { 0x02d1 }, + { 0x0387 }, + { 0x0640 }, + { 0x0e46 }, + { 0x0ec6 }, + { 0x3005 }, + { 0x3031, 0x3035 }, + { 0x309d, 0x309e }, + { 0x30fc, 0x30fe }, +}; + +static void +setTab(char *tab, struct range *ranges, size_t nRanges) +{ + size_t i; + int j; + for (i = 0; i < nRanges; i++) { + if (ranges[i].end) { + for (j = ranges[i].start; j <= ranges[i].end; j++) + tab[j] = 1; + } + else + tab[ranges[i].start] = 1; + } +} + +static void +printTabs(char *tab) +{ + int nBitmaps = 2; + int i, j, k; + unsigned char pageIndex[512]; + + printf( +"static const unsigned namingBitmap[] = {\n\ +0x00000000, 0x00000000, 0x00000000, 0x00000000,\n\ +0x00000000, 0x00000000, 0x00000000, 0x00000000,\n\ +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,\n\ +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,\n"); + for (i = 0; i < 512; i++) { + int kind = tab[i*256]; + for (j = 1; j < 256; j++) + if (tab[i*256 +j] != kind) { + kind = -1; + break; + } + if (i >= 256 && memcmp(tab + (i - 256)*256, tab + i*256, 256) == 0) + pageIndex[i] = pageIndex[i - 256]; + else if (kind == -1) { + pageIndex[i] = nBitmaps++; + for (j = 0; j < 8; j++) { + unsigned val = 0; + for (k = 0; k < 32; k++) { + if (tab[i*256 + j*32 +k]) + val |= (1 << k); + } + printf("0x%08X,", val); + putchar((((j + 1) & 3) == 0) ? '\n' : ' '); + } + } + else + pageIndex[i] = kind; + } + printf("};\n"); + printf("static const unsigned char nmstrtPages[] = {\n"); + for (i = 0; i < 512; i++) { + if (i == 256) + printf("};\nstatic const unsigned char namePages[] = {\n"); + printf("0x%02X,", pageIndex[i]); + putchar((((i + 1) & 7) == 0) ? '\n' : ' '); + } + printf("};\n"); +} + +int +main() +{ + char tab[2*65536]; + memset(tab, 0, 65536); + setTab(tab, nmstrt, sizeof(nmstrt)/sizeof(nmstrt[0])); + memcpy(tab + 65536, tab, 65536); + setTab(tab + 65536, name, sizeof(name)/sizeof(name[0])); + printTabs(tab); + return 0; +} diff --git a/modules/expat/lib/.gitignore b/modules/expat/lib/.gitignore new file mode 100644 index 00000000..9c9cf881 --- /dev/null +++ b/modules/expat/lib/.gitignore @@ -0,0 +1,18 @@ +Makefile +.libs +*.lo +expat.h +Debug +Debug-w +Release +Release-w +expat.ncb +expat.opt +expat.plg +Debug_static +Debug-w_static +Release_static +Release-w_static +expat_static.plg +expatw.plg +expatw_static.plg diff --git a/modules/expat/lib/expat.h b/modules/expat/lib/expat.h index 086e24b3..28b0f954 100644 --- a/modules/expat/lib/expat.h +++ b/modules/expat/lib/expat.h @@ -95,7 +95,9 @@ enum XML_Error { /* Added in 2.0. */ XML_ERROR_RESERVED_PREFIX_XML, XML_ERROR_RESERVED_PREFIX_XMLNS, - XML_ERROR_RESERVED_NAMESPACE_URI + XML_ERROR_RESERVED_NAMESPACE_URI, + /* Added in 2.2.1. */ + XML_ERROR_INVALID_ARGUMENT }; enum XML_Content_Type { @@ -706,6 +708,7 @@ XML_UseParserAsHandlerArg(XML_Parser parser); be called, despite an external subset being parsed. Note: If XML_DTD is not defined when Expat is compiled, returns XML_ERROR_FEATURE_REQUIRES_XML_DTD. + Note: If parser == NULL, returns XML_ERROR_INVALID_ARGUMENT. */ XMLPARSEAPI(enum XML_Error) XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); @@ -729,15 +732,16 @@ XML_GetBase(XML_Parser parser); to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this correspondds to an index into the atts array passed to the - XML_StartElementHandler. + XML_StartElementHandler. Returns -1 if parser == NULL. */ XMLPARSEAPI(int) XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to - XML_StartElementHandler, or -1 if there is no ID attribute. Each - attribute/value pair counts as 2; thus this correspondds to an - index into the atts array passed to the XML_StartElementHandler. + XML_StartElementHandler, or -1 if there is no ID attribute or + parser == NULL. Each attribute/value pair counts as 2; thus this + correspondds to an index into the atts array passed to the + XML_StartElementHandler. */ XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); @@ -901,6 +905,7 @@ enum XML_ParamEntityParsing { entities is requested; otherwise it will return non-zero. Note: If XML_SetParamEntityParsing is called after XML_Parse or XML_ParseBuffer, then it has no effect and will always return 0. + Note: If parser == NULL, the function will do nothing and return 0. */ XMLPARSEAPI(int) XML_SetParamEntityParsing(XML_Parser parser, @@ -910,6 +915,7 @@ XML_SetParamEntityParsing(XML_Parser parser, Helps in preventing DoS attacks based on predicting hash function behavior. This must be called before parsing is started. Returns 1 if successful, 0 when called after parsing has started. + Note: If parser == NULL, the function will do nothing and return 0. */ XMLPARSEAPI(int) XML_SetHashSalt(XML_Parser parser, @@ -936,6 +942,10 @@ XML_GetErrorCode(XML_Parser parser); the location is the location of the character at which the error was detected; otherwise the location is the location of the last parse event, as described above. + + Note: XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber + return 0 to indicate an error. + Note: XML_GetCurrentByteIndex returns -1 to indicate an error. */ XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser); XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser); @@ -1039,7 +1049,7 @@ XML_GetFeatureList(void); */ #define XML_MAJOR_VERSION 2 #define XML_MINOR_VERSION 2 -#define XML_MICRO_VERSION 0 +#define XML_MICRO_VERSION 1 #ifdef __cplusplus } diff --git a/modules/expat/lib/expat.vcxproj b/modules/expat/lib/expat.vcxproj new file mode 100644 index 00000000..1673e676 --- /dev/null +++ b/modules/expat/lib/expat.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + {45A5074D-66E8-44A4-A03F-018027B528D6} + + + + Application + v120 + + + DynamicLibrary + v120 + false + MultiByte + + + DynamicLibrary + v120 + false + MultiByte + + + + + + + + + + + + + + + + + + .\..\win32\bin\Debug\ + .\..\win32\tmp\Debug\ + true + + + .\..\win32\bin\Release\ + .\..\win32\tmp\Release\ + false + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + EditAndContinue + _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + .\..\win32\tmp\Debug\ + true + .\..\win32\tmp\Debug\expat.pch + .\..\win32\tmp\Debug\ + .\..\win32\tmp\Debug\ + EnableFastChecks + + + true + _DEBUG;%(PreprocessorDefinitions) + .\..\win32\bin\Debug\expat.tlb + true + Win32 + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Debug\expat.bsc + + + true + true + true + Console + ..\win32\bin\Debug\libexpat.dll + .\..\win32\bin\Debug\libexpat.lib + .\libexpat.def + + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + .\..\win32\tmp\Release\ + .\..\win32\tmp\Release\expat.pch + + .\..\win32\tmp\Release\ + .\..\win32\tmp\Release\ + + + true + NDEBUG;%(PreprocessorDefinitions) + .\..\win32\bin\Release\expat.tlb + true + Win32 + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Release\expat.bsc + + + true + true + Console + ..\win32\bin\Release\libexpat.dll + .\..\win32\bin\Release\libexpat.lib + .\libexpat.def + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/expat/lib/expat.vcxproj.filters b/modules/expat/lib/expat.vcxproj.filters new file mode 100644 index 00000000..34aea26d --- /dev/null +++ b/modules/expat/lib/expat.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {f01bb743-0ef8-4601-bc44-378fc0abe768} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {c22177dc-5748-4bb1-816e-df311093bf72} + h;hpp;hxx;hm;inl + + + {41146e15-3129-4e5e-bb0f-6b78bb4701b9} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/modules/expat/lib/expat_external.h b/modules/expat/lib/expat_external.h index aa08a2f8..892eb4bb 100644 --- a/modules/expat/lib/expat_external.h +++ b/modules/expat/lib/expat_external.h @@ -93,7 +93,10 @@ extern "C" { #endif #ifdef XML_UNICODE_WCHAR_T -#define XML_UNICODE +# define XML_UNICODE +# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2) +# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc" +# endif #endif #ifdef XML_UNICODE /* Information is UTF-16 encoded. */ diff --git a/modules/expat/lib/expat_static.vcxproj b/modules/expat/lib/expat_static.vcxproj new file mode 100644 index 00000000..77c0ece9 --- /dev/null +++ b/modules/expat/lib/expat_static.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + {58A821BC-E4AF-4DF4-9A54-2BAA22B92615} + + + + Application + v120 + + + StaticLibrary + v120 + false + MultiByte + + + StaticLibrary + v120 + false + MultiByte + + + + + + + + + + + + + + + + + + .\..\win32\bin\Release\ + .\..\win32\tmp\Release_static\ + false + + + .\..\win32\bin\Debug\ + .\..\win32\tmp\Debug_static\ + true + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + _WINDOWS;NDEBUG;_LIB;%(PreprocessorDefinitions) + .\..\win32\tmp\Release_static\ + .\..\win32\tmp\Release_static\expat_static.pch + .\..\win32\tmp\Release_static\ + .\..\win32\tmp\Release_static\ + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Release\expat_static.bsc + + + true + ..\win32\bin\Release\libexpatMT.lib + + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + EditAndContinue + _DEBUG;_WINDOWS;_LIB;%(PreprocessorDefinitions) + .\..\win32\tmp\Debug_static\ + true + .\..\win32\tmp\Debug_static\expat_static.pch + .\..\win32\tmp\Debug_static\ + .\..\win32\tmp\Debug_static\ + EnableFastChecks + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Debug\expat_static.bsc + + + true + ..\win32\bin\Debug\libexpatMT.lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/expat/lib/expat_static.vcxproj.filters b/modules/expat/lib/expat_static.vcxproj.filters new file mode 100644 index 00000000..e6d9d80f --- /dev/null +++ b/modules/expat/lib/expat_static.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {ef375f25-3490-4376-8deb-a8a8bebc0194} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {f1cd6f85-7111-4c1b-abad-37c79851ca34} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/modules/expat/lib/expatw.vcxproj b/modules/expat/lib/expatw.vcxproj new file mode 100644 index 00000000..cf54fd2a --- /dev/null +++ b/modules/expat/lib/expatw.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + {C04F1C11-7079-48AD-A90B-6F59B7A55BEF} + + + + Application + v120 + + + DynamicLibrary + v120 + false + MultiByte + + + DynamicLibrary + v120 + false + MultiByte + + + + + + + + + + + + + + + + + + .\..\win32\bin\Release\ + .\..\win32\tmp\Release-w\ + false + + + .\..\win32\bin\Debug\ + .\..\win32\tmp\Debug-w\ + true + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + NDEBUG;_WINDOWS;_USRDLL;XML_UNICODE_WCHAR_T;%(PreprocessorDefinitions) + .\..\win32\tmp\Release-w\ + .\..\win32\tmp\Release-w\expatw.pch + + .\..\win32\tmp\Release-w\ + .\..\win32\tmp\Release-w\ + + + true + NDEBUG;%(PreprocessorDefinitions) + .\..\win32\bin\Release\expatw.tlb + true + Win32 + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Release\expatw.bsc + + + true + true + Console + ..\win32\bin\Release\libexpatw.dll + .\..\win32\bin\Release\libexpatw.lib + .\libexpatw.def + + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + EditAndContinue + _DEBUG;_WINDOWS;_USRDLL;XML_UNICODE_WCHAR_T;%(PreprocessorDefinitions) + .\..\win32\tmp\Debug-w\ + true + .\..\win32\tmp\Debug-w\expatw.pch + .\..\win32\tmp\Debug-w\ + .\..\win32\tmp\Debug-w\ + EnableFastChecks + + + true + _DEBUG;%(PreprocessorDefinitions) + .\..\win32\bin\Debug\expatw.tlb + true + Win32 + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Debug\expatw.bsc + + + true + true + true + Console + ..\win32\bin\Debug\libexpatw.dll + .\..\win32\bin\Debug\libexpatw.lib + .\libexpatw.def + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/expat/lib/expatw.vcxproj.filters b/modules/expat/lib/expatw.vcxproj.filters new file mode 100644 index 00000000..dc6e9685 --- /dev/null +++ b/modules/expat/lib/expatw.vcxproj.filters @@ -0,0 +1,80 @@ + + + + + {fea8fd20-7d6d-4664-a821-1ab5a29dadbd} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {0ceb9aa0-672d-4a6b-bff9-345c51aab04c} + h;hpp;hxx;hm;inl + + + {d62ff6fc-7f74-443d-a048-31ef02a6f99f} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/modules/expat/lib/expatw_static.vcxproj b/modules/expat/lib/expatw_static.vcxproj new file mode 100644 index 00000000..99a45e47 --- /dev/null +++ b/modules/expat/lib/expatw_static.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + {9220B0F2-C895-4CB2-91D1-1C16C4ECB759} + + + + Application + v120 + + + StaticLibrary + v120 + false + MultiByte + + + StaticLibrary + v120 + false + MultiByte + + + + + + + + + + + + + + + + + + .\..\win32\bin\Debug\ + .\..\win32\tmp\Debug-w_static\ + true + + + .\..\win32\bin\Release\ + .\..\win32\tmp\Release-w_static\ + false + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + EditAndContinue + _DEBUG;_WINDOWS;_LIB;XML_UNICODE_WCHAR_T;%(PreprocessorDefinitions) + .\..\win32\tmp\Debug-w_static\ + true + .\..\win32\tmp\Debug-w_static\expatw_static.pch + .\..\win32\tmp\Debug-w_static\ + .\..\win32\tmp\Debug-w_static\ + EnableFastChecks + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Debug\expatw_static.bsc + + + true + ..\win32\bin\Debug\libexpatwMT.lib + + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + _WINDOWS;NDEBUG;_LIB;XML_UNICODE_WCHAR_T;%(PreprocessorDefinitions) + .\..\win32\tmp\Release-w_static\ + .\..\win32\tmp\Release-w_static\expatw_static.pch + .\..\win32\tmp\Release-w_static\ + .\..\win32\tmp\Release-w_static\ + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Release\expatw_static.bsc + + + true + ..\win32\bin\Release\libexpatwMT.lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/expat/lib/expatw_static.vcxproj.filters b/modules/expat/lib/expatw_static.vcxproj.filters new file mode 100644 index 00000000..83a7c08c --- /dev/null +++ b/modules/expat/lib/expatw_static.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {c0226397-04be-42b5-ba75-257ac91ef7fa} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {3d74dc56-3aec-4ee9-b700-7203f44e015d} + h;hpp;hxx;hm;inl + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/modules/expat/lib/siphash.h b/modules/expat/lib/siphash.h new file mode 100644 index 00000000..3c5fef49 --- /dev/null +++ b/modules/expat/lib/siphash.h @@ -0,0 +1,355 @@ +/* ========================================================================== + * siphash.h - SipHash-2-4 in a single header file + * -------------------------------------------------------------------------- + * Derived by William Ahern from the reference implementation[1] published[2] + * by Jean-Philippe Aumasson and Daniel J. Berstein. Licensed in kind. + * by Jean-Philippe Aumasson and Daniel J. Berstein. + * Minimal changes by Sebastian Pipping on top, details below. + * Licensed under the CC0 Public Domain Dedication license. + * + * 1. https://www.131002.net/siphash/siphash24.c + * 2. https://www.131002.net/siphash/ + * -------------------------------------------------------------------------- + * HISTORY: + * + * 2017-06-18 (Sebastian Pipping) + * - Address lack of stdint.h for Visual Studio 2003 to 2008 + * + * 2017-06-10 (Sebastian Pipping) + * - Clarify license note in the header + * - Address C89 issues: + * - Stop using inline keyword (and let compiler decide) + * - Turn integer suffix ULL to UL + * - Replace _Bool by int + * - Turn macro siphash24 into a function + * - Address invalid conversion (void pointer) by explicit cast + * - Always expose sip24_valid (for self-tests) + * + * 2012-11-04 - Born. (William Ahern) + * -------------------------------------------------------------------------- + * USAGE: + * + * SipHash-2-4 takes as input two 64-bit words as the key, some number of + * message bytes, and outputs a 64-bit word as the message digest. This + * implementation employs two data structures: a struct sipkey for + * representing the key, and a struct siphash for representing the hash + * state. + * + * For converting a 16-byte unsigned char array to a key, use either the + * macro sip_keyof or the routine sip_tokey. The former instantiates a + * compound literal key, while the latter requires a key object as a + * parameter. + * + * unsigned char secret[16]; + * arc4random_buf(secret, sizeof secret); + * struct sipkey *key = sip_keyof(secret); + * + * For hashing a message, use either the convenience macro siphash24 or the + * routines sip24_init, sip24_update, and sip24_final. + * + * struct siphash state; + * void *msg; + * size_t len; + * uint64_t hash; + * + * sip24_init(&state, key); + * sip24_update(&state, msg, len); + * hash = sip24_final(&state); + * + * or + * + * hash = siphash24(msg, len, key); + * + * To convert the 64-bit hash value to a canonical 8-byte little-endian + * binary representation, use either the macro sip_binof or the routine + * sip_tobin. The former instantiates and returns a compound literal array, + * while the latter requires an array object as a parameter. + * -------------------------------------------------------------------------- + * NOTES: + * + * o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers + * lacking compound literal support. Instead, you must use the lower-level + * interfaces which take as parameters the temporary state objects. + * + * o Uppercase macros may evaluate parameters more than once. Lowercase + * macros should not exhibit any such side effects. + * ========================================================================== + */ +#ifndef SIPHASH_H +#define SIPHASH_H + +#include /* size_t */ + +#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600) + /* For vs2003/7.1 up to vs2008/9.0; _MSC_VER 1600 is vs2010/10.0 */ + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; +#else + #include /* uint64_t uint32_t uint8_t */ +#endif + + +#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b)))) + +#define SIP_U32TO8_LE(p, v) \ + (p)[0] = (uint8_t)((v) >> 0); (p)[1] = (uint8_t)((v) >> 8); \ + (p)[2] = (uint8_t)((v) >> 16); (p)[3] = (uint8_t)((v) >> 24); + +#define SIP_U64TO8_LE(p, v) \ + SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \ + SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); + +#define SIP_U8TO64_LE(p) \ + (((uint64_t)((p)[0]) << 0) | \ + ((uint64_t)((p)[1]) << 8) | \ + ((uint64_t)((p)[2]) << 16) | \ + ((uint64_t)((p)[3]) << 24) | \ + ((uint64_t)((p)[4]) << 32) | \ + ((uint64_t)((p)[5]) << 40) | \ + ((uint64_t)((p)[6]) << 48) | \ + ((uint64_t)((p)[7]) << 56)) + + +#define SIPHASH_INITIALIZER { 0, 0, 0, 0, { 0 }, 0, 0 } + +struct siphash { + uint64_t v0, v1, v2, v3; + + unsigned char buf[8], *p; + uint64_t c; +}; /* struct siphash */ + + +#define SIP_KEYLEN 16 + +struct sipkey { + uint64_t k[2]; +}; /* struct sipkey */ + +#define sip_keyof(k) sip_tokey(&(struct sipkey){ { 0 } }, (k)) + +static struct sipkey *sip_tokey(struct sipkey *key, const void *src) { + key->k[0] = SIP_U8TO64_LE((const unsigned char *)src); + key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8); + return key; +} /* sip_tokey() */ + + +#define sip_binof(v) sip_tobin((unsigned char[8]){ 0 }, (v)) + +static void *sip_tobin(void *dst, uint64_t u64) { + SIP_U64TO8_LE((unsigned char *)dst, u64); + return dst; +} /* sip_tobin() */ + + +static void sip_round(struct siphash *H, const int rounds) { + int i; + + for (i = 0; i < rounds; i++) { + H->v0 += H->v1; + H->v1 = SIP_ROTL(H->v1, 13); + H->v1 ^= H->v0; + H->v0 = SIP_ROTL(H->v0, 32); + + H->v2 += H->v3; + H->v3 = SIP_ROTL(H->v3, 16); + H->v3 ^= H->v2; + + H->v0 += H->v3; + H->v3 = SIP_ROTL(H->v3, 21); + H->v3 ^= H->v0; + + H->v2 += H->v1; + H->v1 = SIP_ROTL(H->v1, 17); + H->v1 ^= H->v2; + H->v2 = SIP_ROTL(H->v2, 32); + } +} /* sip_round() */ + + +static struct siphash *sip24_init(struct siphash *H, const struct sipkey *key) { + H->v0 = 0x736f6d6570736575UL ^ key->k[0]; + H->v1 = 0x646f72616e646f6dUL ^ key->k[1]; + H->v2 = 0x6c7967656e657261UL ^ key->k[0]; + H->v3 = 0x7465646279746573UL ^ key->k[1]; + + H->p = H->buf; + H->c = 0; + + return H; +} /* sip24_init() */ + + +#define sip_endof(a) (&(a)[sizeof (a) / sizeof *(a)]) + +static struct siphash *sip24_update(struct siphash *H, const void *src, size_t len) { + const unsigned char *p = (const unsigned char *)src, *pe = p + len; + uint64_t m; + + do { + while (p < pe && H->p < sip_endof(H->buf)) + *H->p++ = *p++; + + if (H->p < sip_endof(H->buf)) + break; + + m = SIP_U8TO64_LE(H->buf); + H->v3 ^= m; + sip_round(H, 2); + H->v0 ^= m; + + H->p = H->buf; + H->c += 8; + } while (p < pe); + + return H; +} /* sip24_update() */ + + +static uint64_t sip24_final(struct siphash *H) { + char left = H->p - H->buf; + uint64_t b = (H->c + left) << 56; + + switch (left) { + case 7: b |= (uint64_t)H->buf[6] << 48; + case 6: b |= (uint64_t)H->buf[5] << 40; + case 5: b |= (uint64_t)H->buf[4] << 32; + case 4: b |= (uint64_t)H->buf[3] << 24; + case 3: b |= (uint64_t)H->buf[2] << 16; + case 2: b |= (uint64_t)H->buf[1] << 8; + case 1: b |= (uint64_t)H->buf[0] << 0; + case 0: break; + } + + H->v3 ^= b; + sip_round(H, 2); + H->v0 ^= b; + H->v2 ^= 0xff; + sip_round(H, 4); + + return H->v0 ^ H->v1 ^ H->v2 ^ H->v3; +} /* sip24_final() */ + + +static uint64_t siphash24(const void *src, size_t len, const struct sipkey *key) { + struct siphash state = SIPHASH_INITIALIZER; + return sip24_final(sip24_update(sip24_init(&state, key), src, len)); +} /* siphash24() */ + + +/* + * SipHash-2-4 output with + * k = 00 01 02 ... + * and + * in = (empty string) + * in = 00 (1 byte) + * in = 00 01 (2 bytes) + * in = 00 01 02 (3 bytes) + * ... + * in = 00 01 02 ... 3e (63 bytes) + */ +static int sip24_valid(void) { + static const unsigned char vectors[64][8] = { + { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, }, + { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, }, + { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, }, + { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, }, + { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, }, + { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, }, + { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, }, + { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, }, + { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, }, + { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, }, + { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, }, + { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, }, + { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, }, + { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, }, + { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, }, + { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, }, + { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, }, + { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, }, + { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, }, + { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, }, + { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, }, + { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, }, + { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, }, + { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, }, + { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, }, + { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, }, + { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, }, + { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, }, + { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, }, + { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, }, + { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, }, + { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, }, + { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, }, + { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, }, + { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, }, + { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, }, + { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, }, + { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, }, + { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, }, + { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, }, + { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, }, + { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, }, + { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, }, + { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, }, + { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, }, + { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, }, + { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, }, + { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, }, + { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, }, + { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, }, + { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, }, + { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, }, + { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, }, + { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, }, + { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, }, + { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, }, + { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, }, + { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, }, + { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, }, + { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, }, + { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, }, + { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, }, + { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, }, + { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, } + }; + unsigned char in[64]; + struct sipkey k; + size_t i; + + sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"); + + for (i = 0; i < sizeof in; ++i) { + in[i] = i; + + if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i])) + return 0; + } + + return 1; +} /* sip24_valid() */ + + +#if SIPHASH_MAIN + +#include + +int main(void) { + int ok = sip24_valid(); + + if (ok) + puts("OK"); + else + puts("FAIL"); + + return !ok; +} /* main() */ + +#endif /* SIPHASH_MAIN */ + + +#endif /* SIPHASH_H */ diff --git a/modules/expat/lib/winconfig.h b/modules/expat/lib/winconfig.h index c1b791d6..9bf014d7 100644 --- a/modules/expat/lib/winconfig.h +++ b/modules/expat/lib/winconfig.h @@ -17,6 +17,12 @@ #include #include + +#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */ +# include +#else /* !defined(HAVE_EXPAT_CONFIG_H) */ + + #define XML_NS 1 #define XML_DTD 1 #define XML_CONTEXT_BYTES 1024 @@ -27,4 +33,8 @@ /* Windows has memmove() available. */ #define HAVE_MEMMOVE + +#endif /* !defined(HAVE_EXPAT_CONFIG_H) */ + + #endif /* ndef WINCONFIG_H */ diff --git a/modules/expat/lib/xmlparse.c b/modules/expat/lib/xmlparse.c index b308e67e..76f078e2 100644 --- a/modules/expat/lib/xmlparse.c +++ b/modules/expat/lib/xmlparse.c @@ -1,13 +1,19 @@ /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd See the file COPYING for copying permission. + + 77fea421d361dca90041d0040ecf1dca651167fadf2af79e990e35168d70d933 (2.2.1+) */ +#define _GNU_SOURCE /* syscall prototype */ + #include #include /* memset(), memcpy() */ #include #include /* UINT_MAX */ +#include /* fprintf */ +#include /* getenv */ -#ifdef WIN32 +#ifdef _WIN32 #define getpid GetCurrentProcessId #else #include /* gettimeofday() */ @@ -17,20 +23,15 @@ #define XML_BUILDING_EXPAT 1 -#ifdef WIN32 +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #elif defined(HAVE_EXPAT_CONFIG_H) #include -#endif /* ndef WIN32 */ +#endif /* ndef _WIN32 */ #include "ascii.h" #include "expat.h" +#include "siphash.h" #ifdef XML_UNICODE #define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX @@ -109,17 +110,11 @@ typedef struct { const XML_Memory_Handling_Suite *mem; } HASH_TABLE; -/* Basic character hash algorithm, taken from Python's string hash: - h = h * 1000003 ^ character, the constant being a prime number. +static size_t +keylen(KEY s); -*/ -#ifdef XML_UNICODE -#define CHAR_HASH(h, c) \ - (((h) * 0xF4243) ^ (unsigned short)(c)) -#else -#define CHAR_HASH(h, c) \ - (((h) * 0xF4243) ^ (unsigned char)(c)) -#endif +static void +copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key); /* For probing (after a collision) we need a step size relative prime to the hash table size, which is a power of 2. We use double-hashing, @@ -355,6 +350,8 @@ doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr, XML_Bool haveMore); #endif /* XML_DTD */ +static void +freeBindings(XML_Parser parser, BINDING *bindings); static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, TAG_NAME *tagNamePtr, BINDING **bindingsPtr); @@ -697,10 +694,84 @@ static const XML_Char implicitContext[] = { ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0' }; + +#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) +# include + +# if defined(HAVE_GETRANDOM) +# include /* getrandom */ +# else +# include /* syscall */ +# include /* SYS_getrandom */ +# endif + +/* Obtain entropy on Linux 3.17+ */ +static int +writeRandomBytes_getrandom(void * target, size_t count) { + int success = 0; /* full count bytes written? */ + size_t bytesWrittenTotal = 0; + const unsigned int getrandomFlags = 0; + + do { + void * const currentTarget = (void*)((char*)target + bytesWrittenTotal); + const size_t bytesToWrite = count - bytesWrittenTotal; + + const int bytesWrittenMore = +#if defined(HAVE_GETRANDOM) + getrandom(currentTarget, bytesToWrite, getrandomFlags); +#else + syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags); +#endif + + if (bytesWrittenMore > 0) { + bytesWrittenTotal += bytesWrittenMore; + if (bytesWrittenTotal >= count) + success = 1; + } + } while (! success && (errno == EINTR || errno == EAGAIN)); + + return success; +} + +#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ + + +#ifdef _WIN32 + +typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG); + +/* Obtain entropy on Windows XP / Windows Server 2003 and later. + * Hint on RtlGenRandom and the following article from libsodioum. + * + * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI + * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/ + */ +static int +writeRandomBytes_RtlGenRandom(void * target, size_t count) { + int success = 0; /* full count bytes written? */ + const HMODULE advapi32 = LoadLibrary("ADVAPI32.DLL"); + + if (advapi32) { + const RTLGENRANDOM_FUNC RtlGenRandom + = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036"); + if (RtlGenRandom) { + if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) { + success = 1; + } + } + FreeLibrary(advapi32); + } + + return success; +} + +#endif /* _WIN32 */ + + static unsigned long gather_time_entropy(void) { -#ifdef WIN32 +#ifdef _WIN32 FILETIME ft; GetSystemTimeAsFileTime(&ft); /* never fails */ return ft.dwHighDateTime ^ ft.dwLowDateTime; @@ -716,20 +787,62 @@ gather_time_entropy(void) #endif } +#if defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_LIBBSD) +# include +#endif + +static unsigned long +ENTROPY_DEBUG(const char * label, unsigned long entropy) { + const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG"); + if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) { + fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", + label, + (int)sizeof(entropy) * 2, entropy, + (unsigned long)sizeof(entropy)); + } + return entropy; +} + static unsigned long generate_hash_secret_salt(XML_Parser parser) { - /* Process ID is 0 bits entropy if attacker has local access - * XML_Parser address is few bits of entropy if attacker has local access */ - const unsigned long entropy = - gather_time_entropy() ^ getpid() ^ (unsigned long)parser; + unsigned long entropy; + (void)parser; +#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__) + (void)gather_time_entropy; + arc4random_buf(&entropy, sizeof(entropy)); + return ENTROPY_DEBUG("arc4random_buf", entropy); +#else + /* Try high quality providers first .. */ +#ifdef _WIN32 + if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) { + return ENTROPY_DEBUG("RtlGenRandom", entropy); + } +#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) + if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) { + return ENTROPY_DEBUG("getrandom", entropy); + } +#endif + /* .. and self-made low quality for backup: */ + + /* Process ID is 0 bits entropy if attacker has local access */ + entropy = gather_time_entropy() ^ getpid(); /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */ if (sizeof(unsigned long) == 4) { - return entropy * 2147483647; + return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647); } else { - return entropy * (unsigned long)2305843009213693951; + return ENTROPY_DEBUG("fallback(8)", + entropy * (unsigned long)2305843009213693951); } +#endif +} + +static unsigned long +get_hash_secret_salt(XML_Parser parser) { + if (parser->m_parentParser != NULL) + return get_hash_secret_salt(parser->m_parentParser); + return parser->m_hash_secret_salt; } static XML_Bool /* only valid for root parser */ @@ -960,6 +1073,10 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { TAG *tStk; OPEN_INTERNAL_ENTITY *openEntityList; + + if (parser == NULL) + return XML_FALSE; + if (parentParser) return XML_FALSE; /* move tagStack to freeTagList */ @@ -994,6 +1111,8 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) enum XML_Status XMLCALL XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { + if (parser == NULL) + return XML_STATUS_ERROR; /* Block after XML_Parse()/XML_ParseBuffer() has been called. XXX There's no way for the caller to determine which of the XXX possible error cases caused the XML_STATUS_ERROR return. @@ -1017,52 +1136,88 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, { XML_Parser parser = oldParser; DTD *newDtd = NULL; - DTD *oldDtd = _dtd; - XML_StartElementHandler oldStartElementHandler = startElementHandler; - XML_EndElementHandler oldEndElementHandler = endElementHandler; - XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; - XML_ProcessingInstructionHandler oldProcessingInstructionHandler - = processingInstructionHandler; - XML_CommentHandler oldCommentHandler = commentHandler; - XML_StartCdataSectionHandler oldStartCdataSectionHandler - = startCdataSectionHandler; - XML_EndCdataSectionHandler oldEndCdataSectionHandler - = endCdataSectionHandler; - XML_DefaultHandler oldDefaultHandler = defaultHandler; - XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler - = unparsedEntityDeclHandler; - XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; - XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler - = startNamespaceDeclHandler; - XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler - = endNamespaceDeclHandler; - XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; - XML_ExternalEntityRefHandler oldExternalEntityRefHandler - = externalEntityRefHandler; - XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler; - XML_UnknownEncodingHandler oldUnknownEncodingHandler - = unknownEncodingHandler; - XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; - XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; - XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; - XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; - ELEMENT_TYPE * oldDeclElementType = declElementType; - - void *oldUserData = userData; - void *oldHandlerArg = handlerArg; - XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities; - XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; + DTD *oldDtd; + XML_StartElementHandler oldStartElementHandler; + XML_EndElementHandler oldEndElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler; + XML_CommentHandler oldCommentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler; + XML_SkippedEntityHandler oldSkippedEntityHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler; + XML_ElementDeclHandler oldElementDeclHandler; + XML_AttlistDeclHandler oldAttlistDeclHandler; + XML_EntityDeclHandler oldEntityDeclHandler; + XML_XmlDeclHandler oldXmlDeclHandler; + ELEMENT_TYPE * oldDeclElementType; + + void *oldUserData; + void *oldHandlerArg; + XML_Bool oldDefaultExpandInternalEntities; + XML_Parser oldExternalEntityRefHandlerArg; #ifdef XML_DTD - enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; - int oldInEntityValue = prologState.inEntityValue; + enum XML_ParamEntityParsing oldParamEntityParsing; + int oldInEntityValue; #endif - XML_Bool oldns_triplets = ns_triplets; + XML_Bool oldns_triplets; /* Note that the new parser shares the same hash secret as the old parser, so that dtdCopy and copyEntityTable can lookup values from hash tables associated with either parser without us having to worry which hash secrets each table has. */ - unsigned long oldhash_secret_salt = hash_secret_salt; + unsigned long oldhash_secret_salt; + + /* Validate the oldParser parameter before we pull everything out of it */ + if (oldParser == NULL) + return NULL; + + /* Stash the original parser contents on the stack */ + oldDtd = _dtd; + oldStartElementHandler = startElementHandler; + oldEndElementHandler = endElementHandler; + oldCharacterDataHandler = characterDataHandler; + oldProcessingInstructionHandler = processingInstructionHandler; + oldCommentHandler = commentHandler; + oldStartCdataSectionHandler = startCdataSectionHandler; + oldEndCdataSectionHandler = endCdataSectionHandler; + oldDefaultHandler = defaultHandler; + oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler; + oldNotationDeclHandler = notationDeclHandler; + oldStartNamespaceDeclHandler = startNamespaceDeclHandler; + oldEndNamespaceDeclHandler = endNamespaceDeclHandler; + oldNotStandaloneHandler = notStandaloneHandler; + oldExternalEntityRefHandler = externalEntityRefHandler; + oldSkippedEntityHandler = skippedEntityHandler; + oldUnknownEncodingHandler = unknownEncodingHandler; + oldElementDeclHandler = elementDeclHandler; + oldAttlistDeclHandler = attlistDeclHandler; + oldEntityDeclHandler = entityDeclHandler; + oldXmlDeclHandler = xmlDeclHandler; + oldDeclElementType = declElementType; + + oldUserData = userData; + oldHandlerArg = handlerArg; + oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; +#ifdef XML_DTD + oldParamEntityParsing = paramEntityParsing; + oldInEntityValue = prologState.inEntityValue; +#endif + oldns_triplets = ns_triplets; + /* Note that the new parser shares the same hash secret as the old + parser, so that dtdCopy and copyEntityTable can lookup values + from hash tables associated with either parser without us having + to worry which hash secrets each table has. + */ + oldhash_secret_salt = hash_secret_salt; #ifdef XML_DTD if (!context) @@ -1228,12 +1383,15 @@ XML_ParserFree(XML_Parser parser) void XMLCALL XML_UseParserAsHandlerArg(XML_Parser parser) { - handlerArg = parser; + if (parser != NULL) + handlerArg = parser; } enum XML_Error XMLCALL XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { + if (parser == NULL) + return XML_ERROR_INVALID_ARGUMENT; #ifdef XML_DTD /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) @@ -1248,6 +1406,8 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) void XMLCALL XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { + if (parser == NULL) + return; /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) return; @@ -1257,6 +1417,8 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) void XMLCALL XML_SetUserData(XML_Parser parser, void *p) { + if (parser == NULL) + return; if (handlerArg == userData) handlerArg = userData = p; else @@ -1266,6 +1428,8 @@ XML_SetUserData(XML_Parser parser, void *p) enum XML_Status XMLCALL XML_SetBase(XML_Parser parser, const XML_Char *p) { + if (parser == NULL) + return XML_STATUS_ERROR; if (p) { p = poolCopyString(&_dtd->pool, p); if (!p) @@ -1280,18 +1444,24 @@ XML_SetBase(XML_Parser parser, const XML_Char *p) const XML_Char * XMLCALL XML_GetBase(XML_Parser parser) { + if (parser == NULL) + return NULL; return curBase; } int XMLCALL XML_GetSpecifiedAttributeCount(XML_Parser parser) { + if (parser == NULL) + return -1; return nSpecifiedAtts; } int XMLCALL XML_GetIdAttributeIndex(XML_Parser parser) { + if (parser == NULL) + return -1; return idAttIndex; } @@ -1299,6 +1469,8 @@ XML_GetIdAttributeIndex(XML_Parser parser) const XML_AttrInfo * XMLCALL XML_GetAttributeInfo(XML_Parser parser) { + if (parser == NULL) + return NULL; return attInfo; } #endif @@ -1308,6 +1480,8 @@ XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) { + if (parser == NULL) + return; startElementHandler = start; endElementHandler = end; } @@ -1315,34 +1489,39 @@ XML_SetElementHandler(XML_Parser parser, void XMLCALL XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) { - startElementHandler = start; + if (parser != NULL) + startElementHandler = start; } void XMLCALL XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) { - endElementHandler = end; + if (parser != NULL) + endElementHandler = end; } void XMLCALL XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler) { - characterDataHandler = handler; + if (parser != NULL) + characterDataHandler = handler; } void XMLCALL XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler) { - processingInstructionHandler = handler; + if (parser != NULL) + processingInstructionHandler = handler; } void XMLCALL XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) { - commentHandler = handler; + if (parser != NULL) + commentHandler = handler; } void XMLCALL @@ -1350,6 +1529,8 @@ XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end) { + if (parser == NULL) + return; startCdataSectionHandler = start; endCdataSectionHandler = end; } @@ -1357,19 +1538,23 @@ XML_SetCdataSectionHandler(XML_Parser parser, void XMLCALL XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start) { - startCdataSectionHandler = start; + if (parser != NULL) + startCdataSectionHandler = start; } void XMLCALL XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end) { - endCdataSectionHandler = end; + if (parser != NULL) + endCdataSectionHandler = end; } void XMLCALL XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) { + if (parser == NULL) + return; defaultHandler = handler; defaultExpandInternalEntities = XML_FALSE; } @@ -1378,6 +1563,8 @@ void XMLCALL XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) { + if (parser == NULL) + return; defaultHandler = handler; defaultExpandInternalEntities = XML_TRUE; } @@ -1387,6 +1574,8 @@ XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end) { + if (parser == NULL) + return; startDoctypeDeclHandler = start; endDoctypeDeclHandler = end; } @@ -1394,27 +1583,31 @@ XML_SetDoctypeDeclHandler(XML_Parser parser, void XMLCALL XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start) { - startDoctypeDeclHandler = start; + if (parser != NULL) + startDoctypeDeclHandler = start; } void XMLCALL XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) { - endDoctypeDeclHandler = end; + if (parser != NULL) + endDoctypeDeclHandler = end; } void XMLCALL XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler) { - unparsedEntityDeclHandler = handler; + if (parser != NULL) + unparsedEntityDeclHandler = handler; } void XMLCALL XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) { - notationDeclHandler = handler; + if (parser != NULL) + notationDeclHandler = handler; } void XMLCALL @@ -1422,6 +1615,8 @@ XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end) { + if (parser == NULL) + return; startNamespaceDeclHandler = start; endNamespaceDeclHandler = end; } @@ -1429,32 +1624,38 @@ XML_SetNamespaceDeclHandler(XML_Parser parser, void XMLCALL XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start) { - startNamespaceDeclHandler = start; + if (parser != NULL) + startNamespaceDeclHandler = start; } void XMLCALL XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end) { - endNamespaceDeclHandler = end; + if (parser != NULL) + endNamespaceDeclHandler = end; } void XMLCALL XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler) { - notStandaloneHandler = handler; + if (parser != NULL) + notStandaloneHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler) { - externalEntityRefHandler = handler; + if (parser != NULL) + externalEntityRefHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) { + if (parser == NULL) + return; if (arg) externalEntityRefHandlerArg = (XML_Parser)arg; else @@ -1465,7 +1666,8 @@ void XMLCALL XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler) { - skippedEntityHandler = handler; + if (parser != NULL) + skippedEntityHandler = handler; } void XMLCALL @@ -1473,6 +1675,8 @@ XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *data) { + if (parser == NULL) + return; unknownEncodingHandler = handler; unknownEncodingHandlerData = data; } @@ -1481,33 +1685,39 @@ void XMLCALL XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) { - elementDeclHandler = eldecl; + if (parser != NULL) + elementDeclHandler = eldecl; } void XMLCALL XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) { - attlistDeclHandler = attdecl; + if (parser != NULL) + attlistDeclHandler = attdecl; } void XMLCALL XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) { - entityDeclHandler = handler; + if (parser != NULL) + entityDeclHandler = handler; } void XMLCALL XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) { - xmlDeclHandler = handler; + if (parser != NULL) + xmlDeclHandler = handler; } int XMLCALL XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing peParsing) { + if (parser == NULL) + return 0; /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) return 0; @@ -1523,6 +1733,10 @@ int XMLCALL XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) { + if (parser == NULL) + return 0; + if (parser->m_parentParser) + return XML_SetHashSalt(parser->m_parentParser, hash_salt); /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED) return 0; @@ -1533,6 +1747,10 @@ XML_SetHashSalt(XML_Parser parser, enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { + if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) { + errorCode = XML_ERROR_INVALID_ARGUMENT; + return XML_STATUS_ERROR; + } switch (ps_parsing) { case XML_SUSPENDED: errorCode = XML_ERROR_SUSPENDED; @@ -1585,6 +1803,13 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) const char *end; int nLeftOver; enum XML_Status result; + /* Detect overflow (a+b > MAX <==> b > MAX-a) */ + if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = NULL; + processor = errorProcessor; + return XML_STATUS_ERROR; + } parseEndByteIndex += len; positionPtr = s; ps_finalBuffer = (XML_Bool)isFinal; @@ -1617,11 +1842,14 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) nLeftOver = s + len - end; if (nLeftOver) { if (buffer == NULL || nLeftOver > bufferLim - buffer) { - /* FIXME avoid integer overflow */ - char *temp; - temp = (buffer == NULL - ? (char *)MALLOC(len * 2) - : (char *)REALLOC(buffer, len * 2)); + /* avoid _signed_ integer overflow */ + char *temp = NULL; + const int bytesToAllocate = (int)((unsigned)len * 2U); + if (bytesToAllocate > 0) { + temp = (buffer == NULL + ? (char *)MALLOC(bytesToAllocate) + : (char *)REALLOC(buffer, bytesToAllocate)); + } if (temp == NULL) { errorCode = XML_ERROR_NO_MEMORY; eventPtr = eventEndPtr = NULL; @@ -1629,7 +1857,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) return XML_STATUS_ERROR; } buffer = temp; - bufferLim = buffer + len * 2; + bufferLim = buffer + bytesToAllocate; } memcpy(buffer, end, nLeftOver); } @@ -1659,6 +1887,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) const char *start; enum XML_Status result = XML_STATUS_OK; + if (parser == NULL) + return XML_STATUS_ERROR; switch (ps_parsing) { case XML_SUSPENDED: errorCode = XML_ERROR_SUSPENDED; @@ -1712,6 +1942,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) void * XMLCALL XML_GetBuffer(XML_Parser parser, int len) { + if (parser == NULL) + return NULL; if (len < 0) { errorCode = XML_ERROR_NO_MEMORY; return NULL; @@ -1808,6 +2040,8 @@ XML_GetBuffer(XML_Parser parser, int len) enum XML_Status XMLCALL XML_StopParser(XML_Parser parser, XML_Bool resumable) { + if (parser == NULL) + return XML_STATUS_ERROR; switch (ps_parsing) { case XML_SUSPENDED: if (resumable) { @@ -1840,6 +2074,8 @@ XML_ResumeParser(XML_Parser parser) { enum XML_Status result = XML_STATUS_OK; + if (parser == NULL) + return XML_STATUS_ERROR; if (ps_parsing != XML_SUSPENDED) { errorCode = XML_ERROR_NOT_SUSPENDED; return XML_STATUS_ERROR; @@ -1876,6 +2112,8 @@ XML_ResumeParser(XML_Parser parser) void XMLCALL XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) { + if (parser == NULL) + return; assert(status != NULL); *status = parser->m_parsingStatus; } @@ -1883,12 +2121,16 @@ XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) enum XML_Error XMLCALL XML_GetErrorCode(XML_Parser parser) { + if (parser == NULL) + return XML_ERROR_INVALID_ARGUMENT; return errorCode; } XML_Index XMLCALL XML_GetCurrentByteIndex(XML_Parser parser) { + if (parser == NULL) + return -1; if (eventPtr) return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr)); return -1; @@ -1897,6 +2139,8 @@ XML_GetCurrentByteIndex(XML_Parser parser) int XMLCALL XML_GetCurrentByteCount(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventEndPtr && eventPtr) return (int)(eventEndPtr - eventPtr); return 0; @@ -1906,11 +2150,19 @@ const char * XMLCALL XML_GetInputContext(XML_Parser parser, int *offset, int *size) { #ifdef XML_CONTEXT_BYTES + if (parser == NULL) + return NULL; if (eventPtr && buffer) { - *offset = (int)(eventPtr - buffer); - *size = (int)(bufferEnd - buffer); + if (offset != NULL) + *offset = (int)(eventPtr - buffer); + if (size != NULL) + *size = (int)(bufferEnd - buffer); return buffer; } +#else + (void)parser; + (void)offset; + (void)size; #endif /* defined XML_CONTEXT_BYTES */ return (char *) 0; } @@ -1918,6 +2170,8 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size) XML_Size XMLCALL XML_GetCurrentLineNumber(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventPtr && eventPtr >= positionPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; @@ -1928,6 +2182,8 @@ XML_GetCurrentLineNumber(XML_Parser parser) XML_Size XMLCALL XML_GetCurrentColumnNumber(XML_Parser parser) { + if (parser == NULL) + return 0; if (eventPtr && eventPtr >= positionPtr) { XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); positionPtr = eventPtr; @@ -1938,30 +2194,38 @@ XML_GetCurrentColumnNumber(XML_Parser parser) void XMLCALL XML_FreeContentModel(XML_Parser parser, XML_Content *model) { - FREE(model); + if (parser != NULL) + FREE(model); } void * XMLCALL XML_MemMalloc(XML_Parser parser, size_t size) { + if (parser == NULL) + return NULL; return MALLOC(size); } void * XMLCALL XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { + if (parser == NULL) + return NULL; return REALLOC(ptr, size); } void XMLCALL XML_MemFree(XML_Parser parser, void *ptr) { - FREE(ptr); + if (parser != NULL) + FREE(ptr); } void XMLCALL XML_DefaultCurrent(XML_Parser parser) { + if (parser == NULL) + return; if (defaultHandler) { if (openInternalEntities) reportDefault(parser, @@ -2468,7 +2732,7 @@ doContent(XML_Parser parser, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); convLen = (int)(toPtr - (XML_Char *)tag->buf); - if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { + if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { tag->name.strLen = convLen; break; } @@ -2511,8 +2775,10 @@ doContent(XML_Parser parser, return XML_ERROR_NO_MEMORY; poolFinish(&tempPool); result = storeAtts(parser, enc, s, &name, &bindings); - if (result) + if (result != XML_ERROR_NONE) { + freeBindings(parser, bindings); return result; + } poolFinish(&tempPool); if (startElementHandler) { startElementHandler(handlerArg, name.str, (const XML_Char **)atts); @@ -2527,15 +2793,7 @@ doContent(XML_Parser parser, if (noElmHandlers && defaultHandler) reportDefault(parser, enc, s, next); poolClear(&tempPool); - while (bindings) { - BINDING *b = bindings; - if (endNamespaceDeclHandler) - endNamespaceDeclHandler(handlerArg, b->prefix->name); - bindings = bindings->nextTagBinding; - b->nextTagBinding = freeBindingList; - freeBindingList = b; - b->prefix->binding = b->prevPrefixBinding; - } + freeBindings(parser, bindings); } if (tagLevel == 0) return epilogProcessor(parser, next, end, nextPtr); @@ -2733,6 +2991,29 @@ doContent(XML_Parser parser, /* not reached */ } +/* This function does not call free() on the allocated memory, merely + * moving it to the parser's freeBindingList where it can be freed or + * reused as appropriate. + */ +static void +freeBindings(XML_Parser parser, BINDING *bindings) +{ + while (bindings) { + BINDING *b = bindings; + + /* startNamespaceDeclHandler will have been called for this + * binding in addBindings(), so call the end handler now. + */ + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } +} + /* Precondition: all arguments must be non-NULL; Purpose: - normalize attributes @@ -2957,7 +3238,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, if (s[-1] == 2) { /* prefixed */ ATTRIBUTE_ID *id; const BINDING *b; - unsigned long uriHash = hash_secret_salt; + unsigned long uriHash; + struct siphash sip_state; + struct sipkey sip_key; + + copy_salt_to_sipkey(parser, &sip_key); + sip24_init(&sip_state, &sip_key); + ((XML_Char *)s)[-1] = 0; /* clear flag */ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); if (!id || !id->prefix) @@ -2966,22 +3253,26 @@ storeAtts(XML_Parser parser, const ENCODING *enc, if (!b) return XML_ERROR_UNBOUND_PREFIX; - /* as we expand the name we also calculate its hash value */ for (j = 0; j < b->uriLen; j++) { const XML_Char c = b->uri[j]; if (!poolAppendChar(&tempPool, c)) return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); } + + sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char)); + while (*s++ != XML_T(ASCII_COLON)) ; + + sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char)); + do { /* copies null terminator */ - const XML_Char c = *s; if (!poolAppendChar(&tempPool, *s)) return XML_ERROR_NO_MEMORY; - uriHash = CHAR_HASH(uriHash, c); } while (*s++); + uriHash = (unsigned long)sip24_final(&sip_state); + { /* Check hash table for duplicate of expanded name (uriName). Derived from code in lookup(parser, HASH_TABLE *table, ...). */ @@ -3695,6 +3986,14 @@ entityValueInitProcessor(XML_Parser parser, *nextPtr = next; return XML_ERROR_NONE; } + /* If we get this token, we have the start of what might be a + normal tag, but not a declaration (i.e. it doesn't begin with + "internalEventEndPtr = NULL; textStart = (char *)entity->textPtr; textEnd = (char *)(entity->textPtr + entity->textLen); + /* Set a safe default value in case 'next' does not get set */ + next = textStart; #ifdef XML_DTD if (entity->is_param) { @@ -4916,6 +5217,8 @@ internalEntityProcessor(XML_Parser parser, entity = openEntity->entity; textStart = ((char *)entity->textPtr) + entity->processed; textEnd = (char *)(entity->textPtr + entity->textLen); + /* Set a safe default value in case 'next' does not get set */ + next = textStart; #ifdef XML_DTD if (entity->is_param) { @@ -5876,7 +6179,6 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_H newE->defaultAtts = (DEFAULT_ATTRIBUTE *) ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (!newE->defaultAtts) { - ms->free_fcn(newE); return 0; } } @@ -6011,13 +6313,32 @@ keyeq(KEY s1, KEY s2) return XML_FALSE; } +static size_t +keylen(KEY s) +{ + size_t len = 0; + for (; *s; s++, len++); + return len; +} + +static void +copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key) +{ + key->k[0] = 0; + key->k[1] = get_hash_secret_salt(parser); +} + static unsigned long FASTCALL hash(XML_Parser parser, KEY s) { - unsigned long h = hash_secret_salt; - while (*s) - h = CHAR_HASH(h, *s++); - return h; + struct siphash state; + struct sipkey key; + (void)sip_tobin; + (void)sip24_valid; + copy_salt_to_sipkey(parser, &key); + sip24_init(&state, &key); + sip24_update(&state, s, keylen(s) * sizeof(XML_Char)); + return (unsigned long)sip24_final(&state); } static NAMED * @@ -6260,6 +6581,35 @@ poolStoreString(STRING_POOL *pool, const ENCODING *enc, return pool->start; } +static size_t +poolBytesToAllocateFor(int blockSize) +{ + /* Unprotected math would be: + ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char); + ** + ** Detect overflow, avoiding _signed_ overflow undefined behavior + ** For a + b * c we check b * c in isolation first, so that addition of a + ** on top has no chance of making us accept a small non-negative number + */ + const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */ + + if (blockSize <= 0) + return 0; + + if (blockSize > (int)(INT_MAX / stretch)) + return 0; + + { + const int stretchedBlockSize = blockSize * (int)stretch; + const int bytesToAllocate = (int)( + offsetof(BLOCK, s) + (unsigned)stretchedBlockSize); + if (bytesToAllocate < 0) + return 0; + + return (size_t)bytesToAllocate; + } +} + static XML_Bool FASTCALL poolGrow(STRING_POOL *pool) { @@ -6289,14 +6639,17 @@ poolGrow(STRING_POOL *pool) if (pool->blocks && pool->start == pool->blocks->s) { BLOCK *temp; int blockSize = (int)((unsigned)(pool->end - pool->start)*2U); + size_t bytesToAllocate; if (blockSize < 0) return XML_FALSE; + bytesToAllocate = poolBytesToAllocateFor(blockSize); + if (bytesToAllocate == 0) + return XML_FALSE; + temp = (BLOCK *) - pool->mem->realloc_fcn(pool->blocks, - (offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char))); + pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate); if (temp == NULL) return XML_FALSE; pool->blocks = temp; @@ -6308,16 +6661,26 @@ poolGrow(STRING_POOL *pool) else { BLOCK *tem; int blockSize = (int)(pool->end - pool->start); + size_t bytesToAllocate; if (blockSize < 0) return XML_FALSE; if (blockSize < INIT_BLOCK_SIZE) blockSize = INIT_BLOCK_SIZE; - else + else { + /* Detect overflow, avoiding _signed_ overflow undefined behavior */ + if ((int)((unsigned)blockSize * 2U) < 0) { + return XML_FALSE; + } blockSize *= 2; - tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s) - + blockSize * sizeof(XML_Char)); + } + + bytesToAllocate = poolBytesToAllocateFor(blockSize); + if (bytesToAllocate == 0) + return XML_FALSE; + + tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate); if (!tem) return XML_FALSE; tem->size = blockSize; diff --git a/modules/expat/lib/xmlrole.c b/modules/expat/lib/xmlrole.c index fcd0dc69..a7c56302 100644 --- a/modules/expat/lib/xmlrole.c +++ b/modules/expat/lib/xmlrole.c @@ -4,19 +4,13 @@ #include -#ifdef WIN32 +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #else #ifdef HAVE_EXPAT_CONFIG_H #include #endif -#endif /* ndef WIN32 */ +#endif /* ndef _WIN32 */ #include "expat_external.h" #include "internal.h" diff --git a/modules/expat/lib/xmltok.c b/modules/expat/lib/xmltok.c index a29d9e2f..cdf0720d 100644 --- a/modules/expat/lib/xmltok.c +++ b/modules/expat/lib/xmltok.c @@ -4,19 +4,13 @@ #include -#ifdef WIN32 +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #else #ifdef HAVE_EXPAT_CONFIG_H #include #endif -#endif /* ndef WIN32 */ +#endif /* ndef _WIN32 */ #include "expat_external.h" #include "internal.h" @@ -369,24 +363,24 @@ utf8_toUtf8(const ENCODING *UNUSED_P(enc), const char **fromP, const char *fromLim, char **toP, const char *toLim) { - enum XML_Convert_Result res = XML_CONVERT_COMPLETED; char *to; const char *from; - if (fromLim - *fromP > toLim - *toP) { - /* Avoid copying partial characters. */ - res = XML_CONVERT_OUTPUT_EXHAUSTED; - fromLim = *fromP + (toLim - *toP); - align_limit_to_full_utf8_characters(*fromP, &fromLim); - } + const char *fromLimInitial = fromLim; + + /* Avoid copying partial characters. */ + align_limit_to_full_utf8_characters(*fromP, &fromLim); + for (to = *toP, from = *fromP; (from < fromLim) && (to < toLim); from++, to++) *to = *from; *fromP = from; *toP = to; - if ((to == toLim) && (from < fromLim)) + if (fromLim < fromLimInitial) + return XML_CONVERT_INPUT_INCOMPLETE; + else if ((to == toLim) && (from < fromLim)) return XML_CONVERT_OUTPUT_EXHAUSTED; else - return res; + return XML_CONVERT_COMPLETED; } static enum XML_Convert_Result PTRCALL @@ -402,7 +396,7 @@ utf8_toUtf16(const ENCODING *enc, case BT_LEAD2: if (fromLim - from < 2) { res = XML_CONVERT_INPUT_INCOMPLETE; - break; + goto after; } *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f)); from += 2; @@ -410,7 +404,7 @@ utf8_toUtf16(const ENCODING *enc, case BT_LEAD3: if (fromLim - from < 3) { res = XML_CONVERT_INPUT_INCOMPLETE; - break; + goto after; } *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f)); @@ -441,6 +435,8 @@ utf8_toUtf16(const ENCODING *enc, break; } } + if (from < fromLim) + res = XML_CONVERT_OUTPUT_EXHAUSTED; after: *fromP = from; *toP = to; diff --git a/modules/expat/make-release.sh b/modules/expat/make-release.sh new file mode 100755 index 00000000..dc507311 --- /dev/null +++ b/modules/expat/make-release.sh @@ -0,0 +1,75 @@ +#! /bin/bash +# +# make-release.sh: make an Expat release +# +# USAGE: make-release.sh tagname +# +# Note: tagname may be HEAD to just grab the head revision (e.g. for testing) +# + +if test $# != 1; then + echo "USAGE: $0 tagname" + exit 1 +fi + +tmpdir=expat-release.$$ +if test -e $tmpdir; then + echo "ERROR: oops. chose the $tmpdir subdir, but it exists." + exit 1 +fi + +echo "Checking out into temporary area: $tmpdir" +mkdir -p "${tmpdir}" || exit 1 +git archive --format=tar -o /dev/stdout "$1" | ( cd $tmpdir && tar xf -) || exit 1 + +echo "" +echo "----------------------------------------------------------------------" +echo "Preparing $tmpdir for release" +(cd $tmpdir && ./buildconf.sh) || exit 1 +(make -C $tmpdir/doc xmlwf.1) || exit 1 + +# figure out the release version +vsn="`$tmpdir/conftools/get-version.sh $tmpdir/lib/expat.h`" + +echo "" +echo "Release version: $vsn" + +if test "$1" = HEAD ; then + distdir=expat-`date '+%Y-%m-%d'` +else + distdir=expat-$vsn +fi +if test -e $distdir; then + echo "ERROR: for safety, you must manually remove $distdir." + rm -rf $tmpdir + exit 1 +fi +mkdir $distdir || exit 1 + +CPOPTS=-Pp +if (cp --version 2>/dev/null | grep -q 'Free Software Foundation') ; then + # If we're using GNU cp, we can avoid the warnings about forward + # compatibility of the options. + CPOPTS='--parents --preserve' +fi + +echo "" +echo "----------------------------------------------------------------------" +echo "Building $distdir based on the MANIFEST:" +files="`sed -e 's/[ ]:.*$//' $tmpdir/MANIFEST`" +for file in $files; do + echo "Copying $file..." + (cd $tmpdir && cp $CPOPTS $file ../$distdir) || exit 1 +done + +echo "" +echo "----------------------------------------------------------------------" +echo "Removing (temporary) checkout directory..." +rm -rf $tmpdir + +tarball=$distdir.tar.bz2 +echo "Constructing $tarball..." +tar cf - $distdir | bzip2 -9 > $tarball || exit $? +rm -r $distdir + +echo "Done." diff --git a/modules/expat/memory-sanitizer-blacklist.txt b/modules/expat/memory-sanitizer-blacklist.txt new file mode 100644 index 00000000..166e6a14 --- /dev/null +++ b/modules/expat/memory-sanitizer-blacklist.txt @@ -0,0 +1,6 @@ +# Line "hash_secret_salt = generate_hash_secret_salt(parser);" +# is mis-reported as use-of-uninitialized-value because +# its call to writeRandomBytes_getrandom uses syscall +# SYS_getrandom and MemorySanitizer does not seem to understand that +# as writing bytes to that memory (which it does). +fun:startParsing diff --git a/modules/expat/qa.sh b/modules/expat/qa.sh new file mode 100755 index 00000000..56bc3492 --- /dev/null +++ b/modules/expat/qa.sh @@ -0,0 +1,130 @@ +#! /bin/bash +# Copyright (C) 2016 Sebastian Pipping +# Licensed under MIT license + +set -o nounset + +: ${GCC_CC:=gcc} +: ${GCC_CXX:=g++} +: ${CLANG_CC:=clang} +: ${CLANG_CXX:=clang++} + +: ${AR:=ar} +: ${CC:="${CLANG_CC}"} +: ${CXX:="${CLANG_CXX}"} +: ${LD:=ld} +: ${MAKE:=make} + +: ${BASE_FLAGS:="-pipe -Wall -Wextra -pedantic -Wno-overlength-strings"} + +ANNOUNCE() { + local open='\e[1m' + local close='\e[0m' + + echo -e -n "${open}" + echo -n "# $*" + echo -e "${close}" +} + +RUN() { + ANNOUNCE "$@" + env "$@" +} + +main() { + local mode="${1:-}" + shift + + local RUNENV + local BASE_FLAGS="${BASE_FLAGS}" + + case "${mode}" in + address) + # http://clang.llvm.org/docs/AddressSanitizer.html + local CC="${GCC_CC}" + local CXX="${GCC_CXX}" + BASE_FLAGS+=" -g -fsanitize=address -fno-omit-frame-pointer" + ;; + coverage | lib-coverage | app-coverage) + local CC="${GCC_CC}" + local CXX="${GCC_CXX}" + BASE_FLAGS+=" --coverage --no-inline" + ;; + egypt) + BASE_FLAGS+=" -fdump-rtl-expand" + ;; + memory) + # http://clang.llvm.org/docs/MemorySanitizer.html + BASE_FLAGS+=" -fsanitize=memory -fno-omit-frame-pointer -g -O2 -fsanitize-memory-track-origins -fsanitize-blacklist=memory-sanitizer-blacklist.txt" + ;; + ncc) + # http://students.ceid.upatras.gr/~sxanth/ncc/ + local CC="ncc -ncgcc -ncld -ncfabs" + local AR=nccar + local LD=nccld + BASE_FLAGS+=" -fPIC" + ;; + undefined) + # http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html + BASE_FLAGS+=" -fsanitize=undefined" + export UBSAN_OPTIONS=print_stacktrace=1 + ;; + *) + echo "Usage:" 1>&2 + echo " ${0##*/} (address|coverage|lib-coverage|app-coverage|egypt|memory|ncc|undefined)" 1>&2 + exit 1 + ;; + esac + + local CFLAGS="-std=c89 ${BASE_FLAGS} ${CFLAGS:-}" + local CXXFLAGS="-std=c++98 ${BASE_FLAGS} ${CXXFLAGS:-}" + + ( + set -e + + RUN CC="${CC}" CFLAGS="${CFLAGS}" \ + CXX="${CXX}" CXXFLAGS="${CXXFLAGS}" \ + AR="${AR}" \ + LD="${LD}" \ + ./configure "$@" + + RUN "${MAKE}" clean all + + case "${mode}" in + egypt|ncc) + ;; + *) + RUN "${MAKE}" check run-xmltest + ;; + esac + ) + [[ $? -ne 0 ]] && exit 1 + + case "${mode}" in + coverage) + find -name '*.gcda' | sort | xargs gcov + ;; + lib-coverage) + find lib -name '*.gcda' | sort | xargs gcov + ;; + app-coverage) + find lib xmlwf -name '*.gcda' | sort | xargs gcov + ;; + egypt) + local DOT_FORMAT="${DOT_FORMAT:-svg}" + local o="callgraph.${DOT_FORMAT}" + ANNOUNCE "egypt ...... | dot ...... > ${o}" + find -name '*.expand' \ + | sort \ + | xargs -r egypt \ + | unflatten -c 20 \ + | dot -T${DOT_FORMAT} -Grankdir=LR \ + > "${o}" + ;; + ncc) + RUN nccnav ./.libs/libexpat.a.nccout + ;; + esac +} + +main "$@" diff --git a/modules/expat/run.sh.in b/modules/expat/run.sh.in new file mode 100644 index 00000000..ff3fb364 --- /dev/null +++ b/modules/expat/run.sh.in @@ -0,0 +1,12 @@ +#! /usr/bin/env bash +# Copyright (C) 2017 Expat development team +# Licensed under the MIT license + +case "@host@" in +*-mingw*) + exec wine "$@" + ;; +*) + exec "$@" + ;; +esac diff --git a/modules/expat/tests/.gitignore b/modules/expat/tests/.gitignore new file mode 100644 index 00000000..410d083b --- /dev/null +++ b/modules/expat/tests/.gitignore @@ -0,0 +1,9 @@ +/out +/xmlconf +/xmltest.log +Makefile +runtests +runtestspp +xmlts.zip +XML-Test-Suite +.libs diff --git a/modules/expat/tests/benchmark/benchmark.c b/modules/expat/tests/benchmark/benchmark.c index 0f0fd18c..efa2858a 100644 --- a/modules/expat/tests/benchmark/benchmark.c +++ b/modules/expat/tests/benchmark/benchmark.c @@ -4,10 +4,6 @@ #include #include "expat.h" -#if defined(__amigaos__) && defined(__USE_INLINE__) -#include -#endif - #ifdef XML_LARGE_SIZE #define XML_FMT_INT_MOD "ll" #else diff --git a/modules/expat/tests/benchmark/benchmark.sln b/modules/expat/tests/benchmark/benchmark.sln new file mode 100644 index 00000000..bc790bc0 --- /dev/null +++ b/modules/expat/tests/benchmark/benchmark.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcxproj", "{FF89BA66-62C4-49EC-9189-1E7B603A1FD6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Template|Win32 = Template|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF89BA66-62C4-49EC-9189-1E7B603A1FD6}.Debug|Win32.ActiveCfg = Debug|Win32 + {FF89BA66-62C4-49EC-9189-1E7B603A1FD6}.Debug|Win32.Build.0 = Debug|Win32 + {FF89BA66-62C4-49EC-9189-1E7B603A1FD6}.Release|Win32.ActiveCfg = Release|Win32 + {FF89BA66-62C4-49EC-9189-1E7B603A1FD6}.Release|Win32.Build.0 = Release|Win32 + {FF89BA66-62C4-49EC-9189-1E7B603A1FD6}.Template|Win32.ActiveCfg = Template|Win32 + {FF89BA66-62C4-49EC-9189-1E7B603A1FD6}.Template|Win32.Build.0 = Template|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/modules/expat/tests/benchmark/benchmark.vcxproj b/modules/expat/tests/benchmark/benchmark.vcxproj new file mode 100644 index 00000000..0f46e883 --- /dev/null +++ b/modules/expat/tests/benchmark/benchmark.vcxproj @@ -0,0 +1,143 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + {FF89BA66-62C4-49EC-9189-1E7B603A1FD6} + + + + Application + v120 + + + Application + v120 + false + MultiByte + + + Application + v120 + false + MultiByte + + + + + + + + + + + + + + + + + + .\Release\ + .\Release\ + false + + + .\Debug\ + .\Debug\ + true + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + ..\..\lib;%(AdditionalIncludeDirectories) + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\Release\ + .\Release\benchmark.pch + .\Release\ + .\Release\ + + + .\Release\benchmark.tlb + + + 0x1009 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\benchmark.bsc + + + true + Console + .\Release\benchmark.exe + ..\..\win32\bin\Release;%(AdditionalLibraryDirectories) + libexpat.lib;%(AdditionalDependencies) + + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + true + EditAndContinue + ..\..\lib;%(AdditionalIncludeDirectories) + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\benchmark.pch + .\Debug\ + .\Debug\ + EnableFastChecks + + + .\Debug\benchmark.tlb + + + 0x1009 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\benchmark.bsc + + + true + true + Console + .\Debug\benchmark.exe + ..\..\win32\bin\Debug;%(AdditionalLibraryDirectories) + libexpat.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/modules/expat/tests/memcheck.c b/modules/expat/tests/memcheck.c new file mode 100644 index 00000000..0b1e5330 --- /dev/null +++ b/modules/expat/tests/memcheck.c @@ -0,0 +1,173 @@ +/* Copyright (c) 2017 The Expat Maintainers + * Copying is permitted under the MIT license. See the file COPYING + * for details. + * + * memcheck.c : debug allocators for the Expat test suite + */ + +#include +#include +#include "memcheck.h" + + +/* Structures to keep track of what has been allocated. Speed isn't a + * big issue for the tests this is required for, so we will use a + * doubly-linked list to make deletion easier. + */ + +typedef struct allocation_entry { + struct allocation_entry * next; + struct allocation_entry * prev; + void * allocation; + size_t num_bytes; +} AllocationEntry; + +static AllocationEntry *alloc_head = NULL; +static AllocationEntry *alloc_tail = NULL; + +static AllocationEntry *find_allocation(void *ptr); + + +/* Allocate some memory and keep track of it. */ +void * +tracking_malloc(size_t size) +{ + AllocationEntry *entry = malloc(sizeof(AllocationEntry)); + + if (entry == NULL) { + printf("Allocator failure\n"); + return NULL; + } + entry->num_bytes = size; + entry->allocation = malloc(size); + if (entry->allocation == NULL) { + free(entry); + return NULL; + } + entry->next = NULL; + + /* Add to the list of allocations */ + if (alloc_head == NULL) { + entry->prev = NULL; + alloc_head = alloc_tail = entry; + } else { + entry->prev = alloc_tail; + alloc_tail->next = entry; + alloc_tail = entry; + } + + return entry->allocation; +} + +static AllocationEntry * +find_allocation(void *ptr) +{ + AllocationEntry *entry; + + for (entry = alloc_head; entry != NULL; entry = entry->next) { + if (entry->allocation == ptr) { + return entry; + } + } + return NULL; +} + +/* Free some memory and remove the tracking for it */ +void +tracking_free(void *ptr) +{ + AllocationEntry *entry; + + if (ptr == NULL) { + /* There won't be an entry for this */ + return; + } + + entry = find_allocation(ptr); + if (entry != NULL) { + /* This is the relevant allocation. Unlink it */ + if (entry->prev != NULL) + entry->prev->next = entry->next; + else + alloc_head = entry->next; + if (entry->next != NULL) + entry->next->prev = entry->prev; + else + alloc_tail = entry->next; + free(entry); + } else { + printf("Attempting to free unallocated memory at %p\n", ptr); + } + free(ptr); +} + +/* Reallocate some memory and keep track of it */ +void * +tracking_realloc(void *ptr, size_t size) +{ + AllocationEntry *entry; + + if (ptr == NULL) { + /* By definition, this is equivalent to malloc(size) */ + return tracking_malloc(size); + } + if (size == 0) { + /* By definition, this is equivalent to free(ptr) */ + tracking_free(ptr); + return NULL; + } + + /* Find the allocation entry for this memory */ + entry = find_allocation(ptr); + if (entry == NULL) { + printf("Attempting to realloc unallocated memory at %p\n", ptr); + entry = malloc(sizeof(AllocationEntry)); + if (entry == NULL) { + printf("Reallocator failure\n"); + return NULL; + } + entry->allocation = realloc(ptr, size); + if (entry->allocation == NULL) { + free(entry); + return NULL; + } + + /* Add to the list of allocations */ + entry->next = NULL; + if (alloc_head == NULL) { + entry->prev = NULL; + alloc_head = alloc_tail = entry; + } else { + entry->prev = alloc_tail; + alloc_tail->next = entry; + alloc_tail = entry; + } + } else { + entry->allocation = realloc(ptr, size); + if (entry->allocation == NULL) { + /* Realloc semantics say the original is still allocated */ + entry->allocation = ptr; + return NULL; + } + } + + entry->num_bytes = size; + return entry->allocation; +} + +int +tracking_report(void) +{ + AllocationEntry *entry; + + if (alloc_head == NULL) + return 1; + + /* Otherwise we have allocations that haven't been freed */ + for (entry = alloc_head; entry != NULL; entry = entry->next) + { + printf("Allocated %lu bytes at %p\n", + entry->num_bytes, entry->allocation); + } + return 0; +} diff --git a/modules/expat/tests/memcheck.h b/modules/expat/tests/memcheck.h new file mode 100644 index 00000000..2c927241 --- /dev/null +++ b/modules/expat/tests/memcheck.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2017 The Expat Maintainers + * Copying is permitted under the MIT license. See the file COPYING + * for details. + * + * memcheck.h + * + * Interface to allocation functions that will track what has or has + * not been freed. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef XML_MEMCHECK_H +#define XML_MEMCHECK_H 1 + +/* Allocation declarations */ + +void *tracking_malloc(size_t size); +void tracking_free(void *ptr); +void *tracking_realloc(void *ptr, size_t size); + +/* End-of-test check to see if unfreed allocations remain. Returns + * TRUE (1) if there is nothing, otherwise prints a report of the + * remaining allocations and returns FALSE (0). + */ +int tracking_report(void); + +#endif /* XML_MEMCHECK_H */ + +#ifdef __cplusplus +} +#endif diff --git a/modules/expat/tests/minicheck.c b/modules/expat/tests/minicheck.c index 5a1f5ed0..9003d3b7 100644 --- a/modules/expat/tests/minicheck.c +++ b/modules/expat/tests/minicheck.c @@ -63,10 +63,7 @@ tcase_add_test(TCase *tc, tcase_test_function test) size_t new_size = sizeof(tcase_test_function) * nalloc; tcase_test_function *new_tests = realloc(tc->tests, new_size); assert(new_tests != NULL); - if (new_tests != tc->tests) { - free(tc->tests); - tc->tests = new_tests; - } + tc->tests = new_tests; tc->allocated = nalloc; } tc->tests[tc->ntests] = test; diff --git a/modules/expat/tests/minicheck.h b/modules/expat/tests/minicheck.h index 9b06f51a..319c981d 100644 --- a/modules/expat/tests/minicheck.h +++ b/modules/expat/tests/minicheck.h @@ -27,7 +27,8 @@ extern "C" { #endif /* ISO C90 does not support '__func__' predefined identifier */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901) +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901)) || \ + (defined(__GNUC__) && !defined(__STDC_VERSION__)) # define __func__ "(unknown)" #endif diff --git a/modules/expat/tests/runtests.c b/modules/expat/tests/runtests.c index c0cdea99..a689ffad 100644 --- a/modules/expat/tests/runtests.c +++ b/modules/expat/tests/runtests.c @@ -14,18 +14,18 @@ #include #include #include /* ptrdiff_t */ +#include #ifndef __cplusplus # include #endif +#include #include "expat.h" #include "chardata.h" #include "internal.h" /* for UNUSED_P only */ #include "minicheck.h" - -#if defined(__amigaos__) && defined(__USE_INLINE__) -#include -#endif +#include "memcheck.h" +#include "siphash.h" #ifdef XML_LARGE_SIZE #define XML_FMT_INT_MOD "ll" @@ -33,7 +33,7 @@ #define XML_FMT_INT_MOD "l" #endif -static XML_Parser parser; +static XML_Parser parser = NULL; static void @@ -47,8 +47,10 @@ basic_setup(void) static void basic_teardown(void) { - if (parser != NULL) + if (parser != NULL) { XML_ParserFree(parser); + parser = NULL; + } } /* Generate a failure using the parser state to create an error message; @@ -174,6 +176,37 @@ dummy_start_element(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts)) {} +static void XMLCALL +dummy_start_cdata_handler(void *UNUSED_P(userData)) +{} + +static void XMLCALL +dummy_end_cdata_handler(void *UNUSED_P(userData)) +{} + +static void XMLCALL +dummy_start_namespace_decl_handler(void *UNUSED_P(userData), + const XML_Char *UNUSED_P(prefix), + const XML_Char *UNUSED_P(uri)) +{} + +static void XMLCALL +dummy_end_namespace_decl_handler(void *UNUSED_P(userData), + const XML_Char *UNUSED_P(prefix)) +{} + +/* This handler is obsolete, but while the code exists we should + * ensure that dealing with the handler is covered by tests. + */ +static void XMLCALL +dummy_unparsed_entity_decl_handler(void *UNUSED_P(userData), + const XML_Char *UNUSED_P(entityName), + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId), + const XML_Char *UNUSED_P(notationName)) +{} + /* * Character & encoding tests. @@ -201,6 +234,45 @@ START_TEST(test_u0000_char) } END_TEST +START_TEST(test_siphash_self) +{ + if (! sip24_valid()) + fail("SipHash self-test failed"); +} +END_TEST + +START_TEST(test_siphash_spec) +{ + /* https://131002.net/siphash/siphash.pdf (page 19, "Test values") */ + const char message[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" + "\x0a\x0b\x0c\x0d\x0e"; + const size_t len = sizeof(message) - 1; + const uint64_t expected = 0xa129ca6149be45e5U; + struct siphash state; + struct sipkey key; + (void)sip_tobin; + + sip_tokey(&key, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" + "\x0a\x0b\x0c\x0d\x0e\x0f"); + sip24_init(&state, &key); + + /* Cover spread across calls */ + sip24_update(&state, message, 4); + sip24_update(&state, message + 4, len - 4); + + /* Cover null length */ + sip24_update(&state, message, 0); + + if (sip24_final(&state) != expected) + fail("sip24_final failed spec test\n"); + + /* Cover wrapper */ + if (siphash24(message, len, &key) != expected) + fail("siphash24 failed spec test\n"); +} +END_TEST + START_TEST(test_bom_utf8) { /* This test is really just making sure we don't core on a UTF-8 BOM. */ @@ -855,6 +927,37 @@ START_TEST(test_unknown_encoding_internal_entity) } END_TEST +/* Test unrecognised encoding handler */ +static void dummy_release(void *UNUSED_P(data)) +{ +} + +static int XMLCALL +UnrecognisedEncodingHandler(void *UNUSED_P(data), + const XML_Char *UNUSED_P(encoding), + XML_Encoding *info) +{ + info->data = NULL; + info->convert = NULL; + info->release = dummy_release; + return XML_STATUS_ERROR; +} + +START_TEST(test_unrecognised_encoding_internal_entity) +{ + const char *text = + "\n" + "]>\n" + ""; + + XML_SetUnknownEncodingHandler(parser, + UnrecognisedEncodingHandler, + NULL); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + fail("Unrecognised encoding not rejected"); +} +END_TEST + /* Regression test for SF bug #620106. */ static int XMLCALL external_entity_loader_set_encoding(XML_Parser parser, @@ -996,6 +1099,56 @@ START_TEST(test_wfc_undeclared_entity_with_external_subset) { } END_TEST +/* Test that an error is reported if our NotStandalone handler fails */ +static int XMLCALL +reject_not_standalone_handler(void *UNUSED_P(userData)) +{ + return XML_STATUS_ERROR; +} + +START_TEST(test_not_standalone_handler_reject) +{ + const char *text = + "\n" + "\n" + "&entity;"; + char foo_text[] = + ""; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetUserData(parser, foo_text); + XML_SetExternalEntityRefHandler(parser, external_entity_loader); + XML_SetNotStandaloneHandler(parser, reject_not_standalone_handler); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + fail("NotStandalone handler failed to reject"); +} +END_TEST + +/* Test that no error is reported if our NotStandalone handler succeeds */ +static int XMLCALL +accept_not_standalone_handler(void *UNUSED_P(userData)) +{ + return XML_STATUS_OK; +} + +START_TEST(test_not_standalone_handler_accept) +{ + const char *text = + "\n" + "\n" + "&entity;"; + char foo_text[] = + ""; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetUserData(parser, foo_text); + XML_SetExternalEntityRefHandler(parser, external_entity_loader); + XML_SetNotStandaloneHandler(parser, accept_not_standalone_handler); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + START_TEST(test_wfc_no_recursive_entity_refs) { const char *text = @@ -1024,15 +1177,16 @@ START_TEST(test_dtd_default_handling) "]>"; XML_SetDefaultHandler(parser, accumulate_characters); - XML_SetDoctypeDeclHandler(parser, - dummy_start_doctype_handler, - dummy_end_doctype_handler); + XML_SetStartDoctypeDeclHandler(parser, dummy_start_doctype_handler); + XML_SetEndDoctypeDeclHandler(parser, dummy_end_doctype_handler); XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler); XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler); XML_SetElementDeclHandler(parser, dummy_element_decl_handler); XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler); XML_SetProcessingInstructionHandler(parser, dummy_pi_handler); XML_SetCommentHandler(parser, dummy_comment_handler); + XML_SetStartCdataSectionHandler(parser, dummy_start_cdata_handler); + XML_SetEndCdataSectionHandler(parser, dummy_end_cdata_handler); run_character_check(text, "\n\n\n\n\n\n\n"); } END_TEST @@ -1146,9 +1300,74 @@ START_TEST(test_suspend_parser_between_char_data_calls) xml_failure(parser); if (XML_GetErrorCode(parser) != XML_ERROR_NONE) xml_failure(parser); + /* Try parsing directly */ + if (XML_Parse(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + fail("Attempt to continue parse while suspended not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_SUSPENDED) + fail("Suspended parse not faulted with correct error"); +} +END_TEST + + +static XML_Bool abortable = XML_FALSE; + +static void +parser_stop_character_handler(void *UNUSED_P(userData), + const XML_Char *UNUSED_P(s), + int UNUSED_P(len)) +{ + XML_StopParser(parser, resumable); + XML_SetCharacterDataHandler(parser, NULL); + if (!resumable) { + /* Check that aborting an aborted parser is faulted */ + if (XML_StopParser(parser, XML_FALSE) != XML_STATUS_ERROR) + fail("Aborting aborted parser not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_FINISHED) + xml_failure(parser); + } else if (abortable) { + /* Check that aborting a suspended parser works */ + if (XML_StopParser(parser, XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + } else { + /* Check that suspending a suspended parser works */ + if (XML_StopParser(parser, XML_TRUE) != XML_STATUS_ERROR) + fail("Suspending suspended parser not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_SUSPENDED) + xml_failure(parser); + } +} + +/* Test repeated calls to XML_StopParser are handled correctly */ +START_TEST(test_repeated_stop_parser_between_char_data_calls) +{ + const char *text = long_character_data_text; + + XML_SetCharacterDataHandler(parser, parser_stop_character_handler); + resumable = XML_FALSE; + abortable = XML_FALSE; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) != XML_STATUS_ERROR) + fail("Failed to double-stop parser"); + + XML_ParserReset(parser, NULL); + XML_SetCharacterDataHandler(parser, parser_stop_character_handler); + resumable = XML_TRUE; + abortable = XML_FALSE; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) != XML_STATUS_SUSPENDED) + fail("Failed to double-suspend parser"); + + XML_ParserReset(parser, NULL); + XML_SetCharacterDataHandler(parser, parser_stop_character_handler); + resumable = XML_TRUE; + abortable = XML_TRUE; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) != XML_STATUS_ERROR) + fail("Failed to suspend-abort parser"); } END_TEST + START_TEST(test_good_cdata_ascii) { const char *text = "Hello, world!]]>"; @@ -1244,144 +1463,1093 @@ START_TEST(test_bad_cdata) } END_TEST - -/* - * Namespaces tests. - */ - -static void -namespace_setup(void) -{ - parser = XML_ParserCreateNS(NULL, ' '); - if (parser == NULL) - fail("Parser not created."); +/* Test memory allocation functions */ +START_TEST(test_memory_allocation) +{ + char *buffer = (char *)XML_MemMalloc(parser, 256); + char *p; + + if (buffer == NULL) { + fail("Allocation failed"); + } else { + /* Try writing to memory; some OSes try to cheat! */ + buffer[0] = 'T'; + buffer[1] = 'E'; + buffer[2] = 'S'; + buffer[3] = 'T'; + buffer[4] = '\0'; + if (strcmp(buffer, "TEST") != 0) { + fail("Memory not writable"); + } else { + p = (char *)XML_MemRealloc(parser, buffer, 512); + if (p == NULL) { + fail("Reallocation failed"); + } else { + /* Write again, just to be sure */ + buffer = p; + buffer[0] = 'V'; + if (strcmp(buffer, "VEST") != 0) { + fail("Reallocated memory not writable"); + } + } + } + XML_MemFree(parser, buffer); + } } +END_TEST -static void -namespace_teardown(void) +static void XMLCALL +record_default_handler(void *userData, + const XML_Char *UNUSED_P(s), + int UNUSED_P(len)) { - basic_teardown(); + CharData_AppendString((CharData *)userData, "D"); } -/* Check that an element name and attribute name match the expected values. - The expected values are passed as an array reference of string pointers - provided as the userData argument; the first is the expected - element name, and the second is the expected attribute name. -*/ static void XMLCALL -triplet_start_checker(void *userData, const XML_Char *name, - const XML_Char **atts) +record_cdata_handler(void *userData, + const XML_Char *UNUSED_P(s), + int UNUSED_P(len)) { - char **elemstr = (char **)userData; - char buffer[1024]; - if (strcmp(elemstr[0], name) != 0) { - sprintf(buffer, "unexpected start string: '%s'", name); - fail(buffer); - } - if (strcmp(elemstr[1], atts[0]) != 0) { - sprintf(buffer, "unexpected attribute string: '%s'", atts[0]); - fail(buffer); - } + CharData_AppendString((CharData *)userData, "C"); + XML_DefaultCurrent(parser); } -/* Check that the element name passed to the end-element handler matches - the expected value. The expected value is passed as the first element - in an array of strings passed as the userData argument. -*/ static void XMLCALL -triplet_end_checker(void *userData, const XML_Char *name) +record_cdata_nodefault_handler(void *userData, + const XML_Char *UNUSED_P(s), + int UNUSED_P(len)) { - char **elemstr = (char **)userData; - if (strcmp(elemstr[0], name) != 0) { - char buffer[1024]; - sprintf(buffer, "unexpected end string: '%s'", name); - fail(buffer); - } + CharData_AppendString((CharData *)userData, "c"); } -START_TEST(test_return_ns_triplet) +/* Test XML_DefaultCurrent() passes handling on correctly */ +START_TEST(test_default_current) { - const char *text = - ""; - const char *elemstr[] = { - "http://expat.sf.net/ e foo", - "http://expat.sf.net/ a bar" - }; - XML_SetReturnNSTriplet(parser, XML_TRUE); - XML_SetUserData(parser, elemstr); - XML_SetElementHandler(parser, triplet_start_checker, triplet_end_checker); - if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + const char *text = "hello"; + const char *entity_text = + "\n" + "]>\n" + "&entity;"; + CharData storage; + + XML_SetDefaultHandler(parser, record_default_handler); + XML_SetCharacterDataHandler(parser, record_cdata_handler); + CharData_Init(&storage); + XML_SetUserData(parser, &storage); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) xml_failure(parser); -} -END_TEST + CharData_CheckString(&storage, "DCDCDCDCDCDD"); -static void XMLCALL -overwrite_start_checker(void *userData, const XML_Char *name, - const XML_Char **atts) -{ - CharData *storage = (CharData *) userData; - CharData_AppendString(storage, "start "); - CharData_AppendXMLChars(storage, name, -1); - while (*atts != NULL) { - CharData_AppendString(storage, "\nattribute "); - CharData_AppendXMLChars(storage, *atts, -1); - atts += 2; - } - CharData_AppendString(storage, "\n"); -} + /* Again, without the defaulting */ + XML_ParserReset(parser, NULL); + XML_SetDefaultHandler(parser, record_default_handler); + XML_SetCharacterDataHandler(parser, record_cdata_nodefault_handler); + CharData_Init(&storage); + XML_SetUserData(parser, &storage); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + CharData_CheckString(&storage, "DcccccD"); -static void XMLCALL -overwrite_end_checker(void *userData, const XML_Char *name) -{ - CharData *storage = (CharData *) userData; - CharData_AppendString(storage, "end "); - CharData_AppendXMLChars(storage, name, -1); - CharData_AppendString(storage, "\n"); -} + /* Now with an internal entity to complicate matters */ + XML_ParserReset(parser, NULL); + XML_SetDefaultHandler(parser, record_default_handler); + XML_SetCharacterDataHandler(parser, record_cdata_handler); + CharData_Init(&storage); + XML_SetUserData(parser, &storage); + if (_XML_Parse_SINGLE_BYTES(parser, entity_text, strlen(entity_text), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + /* The default handler suppresses the entity */ + CharData_CheckString(&storage, "DDDDDDDDDDDDDDDDDDD"); -static void -run_ns_tagname_overwrite_test(const char *text, const char *result) -{ - CharData storage; + /* This time, allow the entity through */ + XML_ParserReset(parser, NULL); + XML_SetDefaultHandlerExpand(parser, record_default_handler); + XML_SetCharacterDataHandler(parser, record_cdata_handler); CharData_Init(&storage); XML_SetUserData(parser, &storage); - XML_SetElementHandler(parser, - overwrite_start_checker, overwrite_end_checker); - if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + if (_XML_Parse_SINGLE_BYTES(parser, entity_text, strlen(entity_text), + XML_TRUE) == XML_STATUS_ERROR) xml_failure(parser); - CharData_CheckString(&storage, result); + CharData_CheckString(&storage, "DDDDDDDDDDDDDDDDDCDD"); + + /* Finally, without passing the cdata to the default handler */ + XML_ParserReset(parser, NULL); + XML_SetDefaultHandlerExpand(parser, record_default_handler); + XML_SetCharacterDataHandler(parser, record_cdata_nodefault_handler); + CharData_Init(&storage); + XML_SetUserData(parser, &storage); + if (_XML_Parse_SINGLE_BYTES(parser, entity_text, strlen(entity_text), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + CharData_CheckString(&storage, "DDDDDDDDDDDDDDDDDcD"); } +END_TEST -/* Regression test for SF bug #566334. */ -START_TEST(test_ns_tagname_overwrite) +/* Test DTD element parsing code paths */ +START_TEST(test_dtd_elements) { const char *text = - "\n" - " \n" - " \n" - ""; - const char *result = - "start http://xml.libexpat.org/ e\n" - "start http://xml.libexpat.org/ f\n" - "attribute http://xml.libexpat.org/ attr\n" - "end http://xml.libexpat.org/ f\n" - "start http://xml.libexpat.org/ g\n" - "attribute http://xml.libexpat.org/ attr2\n" - "end http://xml.libexpat.org/ g\n" - "end http://xml.libexpat.org/ e\n"; - run_ns_tagname_overwrite_test(text, result); + "\n" + "\n" + "]>\n" + "Wombats are go"; + + XML_SetElementDeclHandler(parser, dummy_element_decl_handler); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); } END_TEST -/* Regression test for SF bug #566334. */ -START_TEST(test_ns_tagname_overwrite_triplet) +/* Test foreign DTD handling */ +START_TEST(test_set_foreign_dtd) { - const char *text = - "\n" - " \n" - " \n" - ""; + const char *text1 = + "\n"; + const char *text2 = + "&entity;"; + char dtd_text[] = ""; + + /* Check hash salt is passed through too */ + XML_SetHashSalt(parser, 0x12345678); + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetUserData(parser, dtd_text); + XML_SetExternalEntityRefHandler(parser, external_entity_loader); + if (XML_UseForeignDTD(parser, XML_TRUE) != XML_ERROR_NONE) + fail("Could not set foreign DTD"); + if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1), + XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + + /* Ensure that trying to set the DTD after parsing has started + * is faulted, even if it's the same setting. + */ + if (XML_UseForeignDTD(parser, XML_TRUE) == XML_ERROR_NONE) + fail("Failed to reject late foreign DTD setting"); + /* Ditto for the hash salt */ + if (XML_SetHashSalt(parser, 0x23456789)) + fail("Failed to reject late hash salt change"); + + /* Now finish the parse */ + if (_XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + +/* Test XML Base is set and unset appropriately */ +START_TEST(test_set_base) +{ + const XML_Char *old_base; + const XML_Char *new_base = "/local/file/name.xml"; + + old_base = XML_GetBase(parser); + if (XML_SetBase(parser, new_base) != XML_STATUS_OK) + fail("Unable to set base"); + if (strcmp(XML_GetBase(parser), new_base) != 0) + fail("Base setting not correct"); + if (XML_SetBase(parser, NULL) != XML_STATUS_OK) + fail("Unable to NULL base"); + if (XML_GetBase(parser) != NULL) + fail("Base setting not nulled"); + XML_SetBase(parser, old_base); +} +END_TEST + +/* Test attribute counts, indexing, etc */ +typedef struct attrInfo { + const char *name; + const char *value; +} AttrInfo; + +typedef struct elementInfo { + const char *name; + int attr_count; + const char *id_name; + AttrInfo *attributes; +} ElementInfo; + +static void XMLCALL +counting_start_element_handler(void *userData, + const XML_Char *name, + const XML_Char **atts) +{ + ElementInfo *info = (ElementInfo *)userData; + AttrInfo *attr; + int count, id, i; + + while (info->name != NULL) { + if (!strcmp(name, info->name)) + break; + info++; + } + if (info->name == NULL) + fail("Element not recognised"); + /* Note attribute count is doubled */ + count = XML_GetSpecifiedAttributeCount(parser); + if (info->attr_count * 2 != count) { + fail("Not got expected attribute count"); + return; + } + id = XML_GetIdAttributeIndex(parser); + if (id == -1 && info->id_name != NULL) { + fail("ID not present"); + return; + } + if (id != -1 && strcmp(atts[id], info->id_name)) { + fail("ID does not have the correct name"); + return; + } + for (i = 0; i < info->attr_count; i++) { + attr = info->attributes; + while (attr->name != NULL) { + if (!strcmp(atts[0], attr->name)) + break; + attr++; + } + if (attr->name == NULL) { + fail("Attribute not recognised"); + return; + } + if (strcmp(atts[1], attr->value)) { + fail("Attribute has wrong value"); + return; + } + atts += 2; + } +} + +START_TEST(test_attributes) +{ + const char *text = + "\n" + "\n" + "]>" + "" + "" + ""; + AttrInfo doc_info[] = { + { "a", "1" }, + { "b", "2" }, + { "id", "one" }, + { NULL, NULL } + }; + AttrInfo tag_info[] = { + { "c", "3" }, + { NULL, NULL } + }; + ElementInfo info[] = { + { "doc", 3, "id", NULL }, + { "tag", 1, NULL, NULL }, + { NULL, 0, NULL, NULL } + }; + info[0].attributes = doc_info; + info[1].attributes = tag_info; + + XML_SetStartElementHandler(parser, counting_start_element_handler); + XML_SetUserData(parser, info); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + +/* Test reset works correctly in the middle of processing an internal + * entity. Exercises some obscure code in XML_ParserReset(). + */ +START_TEST(test_reset_in_entity) +{ + const char *text = + "\n" + "\n" + "]>\n" + "&entity;"; + XML_ParsingStatus status; + + resumable = XML_TRUE; + XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + XML_GetParsingStatus(parser, &status); + if (status.parsing != XML_SUSPENDED) + fail("Parsing status not SUSPENDED"); + XML_ParserReset(parser, NULL); + XML_GetParsingStatus(parser, &status); + if (status.parsing != XML_INITIALIZED) + fail("Parsing status doesn't reset to INITIALIZED"); +} +END_TEST + +/* Test that resume correctly passes through parse errors */ +START_TEST(test_resume_invalid_parse) +{ + const char *text = "Hello\n" + "\n" + "&entity;"; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(parser, external_entity_resetter); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + + +/* Test suspending a subordinate parser */ + +static void XMLCALL +entity_suspending_decl_handler(void *userData, + const XML_Char *UNUSED_P(name), + XML_Content *model) +{ + XML_Parser ext_parser = (XML_Parser)userData; + + if (XML_StopParser(ext_parser, XML_TRUE) != XML_STATUS_ERROR) + fail("Attempting to suspend a subordinate parser not faulted"); + if (XML_GetErrorCode(ext_parser) != XML_ERROR_SUSPEND_PE) + fail("Suspending subordinate parser get wrong code"); + XML_SetElementDeclHandler(ext_parser, NULL); + XML_FreeContentModel(parser, model); +} + +static int XMLCALL +external_entity_suspender(XML_Parser parser, + const XML_Char *context, + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) +{ + const char *text = ""; + XML_Parser ext_parser; + + ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); + if (ext_parser == NULL) + fail("Could not create external entity parser"); + XML_SetElementDeclHandler(ext_parser, entity_suspending_decl_handler); + XML_SetUserData(ext_parser, ext_parser); + if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) { + xml_failure(ext_parser); + return XML_STATUS_ERROR; + } + return XML_STATUS_OK; +} + +START_TEST(test_subordinate_suspend) +{ + const char *text = + "\n" + "\n" + "&entity;"; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(parser, external_entity_suspender); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + + +/* Test setting an explicit encoding */ +START_TEST(test_explicit_encoding) +{ + const char *text1 = "Hello "; + const char *text2 = " World"; + + /* First say we are UTF-8 */ + if (XML_SetEncoding(parser, "utf-8") != XML_STATUS_OK) + fail("Failed to set explicit encoding"); + if (_XML_Parse_SINGLE_BYTES(parser, text1, strlen(text1), + XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + /* Try to switch encodings mid-parse */ + if (XML_SetEncoding(parser, "us-ascii") != XML_STATUS_ERROR) + fail("Allowed encoding change"); + if (_XML_Parse_SINGLE_BYTES(parser, text2, strlen(text2), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + /* Try now the parse is over */ + if (XML_SetEncoding(parser, NULL) != XML_STATUS_OK) + fail("Failed to unset encoding"); +} +END_TEST + +/* Test user parameter settings */ +/* Variable holding the expected handler userData */ +static void *handler_data = NULL; +/* Count of the number of times the comment handler has been invoked */ +static int comment_count = 0; +/* Count of the number of skipped entities */ +static int skip_count = 0; +/* Count of the number of times the XML declaration handler is invoked */ +static int xdecl_count = 0; + +static void XMLCALL +xml_decl_handler(void *userData, + const XML_Char *UNUSED_P(version), + const XML_Char *UNUSED_P(encoding), + int standalone) +{ + if (userData != handler_data) + fail("User data (xml decl) not correctly set"); + if (standalone != -1) + fail("Standalone not show as not present"); + xdecl_count++; +} + +static void XMLCALL +param_check_skip_handler(void *userData, + const XML_Char *UNUSED_P(entityName), + int UNUSED_P(is_parameter_entity)) +{ + if (userData != handler_data) + fail("User data (skip) not correctly set"); + skip_count++; +} + +static void XMLCALL +data_check_comment_handler(void *userData, const XML_Char *UNUSED_P(data)) +{ + /* Check that the userData passed through is what we expect */ + if (userData != handler_data) + fail("User data (parser) not correctly set"); + /* Check that the user data in the parser is appropriate */ + if (XML_GetUserData(userData) != (void *)1) + fail("User data in parser not correctly set"); + comment_count++; +} + +static int XMLCALL +external_entity_param_checker(XML_Parser parser, + const XML_Char *context, + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) +{ + const char *text = + "\n" + ""; + XML_Parser ext_parser; + + ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); + if (ext_parser == NULL) + fail("Could not create external entity parser"); + handler_data = ext_parser; + if (_XML_Parse_SINGLE_BYTES(ext_parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) { + xml_failure(parser); + return XML_STATUS_ERROR; + } + handler_data = parser; + return XML_STATUS_OK; +} + +START_TEST(test_user_parameters) +{ + const char *text = + "\n" + "\n" + "\n" + "&entity;"; + const char *epilog = + "\n" + ""; + + comment_count = 0; + skip_count = 0; + xdecl_count = 0; + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetXmlDeclHandler(parser, xml_decl_handler); + XML_SetExternalEntityRefHandler(parser, external_entity_param_checker); + XML_SetCommentHandler(parser, data_check_comment_handler); + XML_SetSkippedEntityHandler(parser, param_check_skip_handler); + XML_UseParserAsHandlerArg(parser); + XML_SetUserData(parser, (void *)1); + handler_data = parser; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + if (comment_count != 2) + fail("Comment handler not invoked enough times"); + /* Ensure we can't change policy mid-parse */ + if (XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_NEVER)) + fail("Changed param entity parsing policy while parsing"); + if (_XML_Parse_SINGLE_BYTES(parser, epilog, strlen(epilog), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + if (comment_count != 3) + fail("Comment handler not invoked enough times"); + if (skip_count != 1) + fail("Skip handler not invoked enough times"); + if (xdecl_count != 1) + fail("XML declaration handler not invoked"); +} +END_TEST + +/* Test that an explicit external entity handler argument replaces + * the parser as the first argument. + */ +static int XMLCALL +external_entity_ref_param_checker(XML_Parser parser, + const XML_Char *UNUSED_P(context), + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) +{ + if ((void *)parser != handler_data) + fail("External entity ref handler parameter not correct"); + return XML_STATUS_OK; +} + +START_TEST(test_ext_entity_ref_parameter) +{ + const char *text = + "\n" + "\n" + "&entity;"; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(parser, + external_entity_ref_param_checker); + /* Set a handler arg that is not NULL and not parser (which is + * what NULL would cause to be passed. + */ + XML_SetExternalEntityRefHandlerArg(parser, (void *)text); + handler_data = (void *)text; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + + /* Now try again with unset args */ + XML_ParserReset(parser, NULL); + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(parser, + external_entity_ref_param_checker); + XML_SetExternalEntityRefHandlerArg(parser, NULL); + handler_data = (void *)parser; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + +/* Test the parsing of an empty string */ +START_TEST(test_empty_parse) +{ + const char *text = ""; + const char *partial = ""; + + if (XML_Parse(parser, NULL, 0, XML_FALSE) == XML_STATUS_ERROR) + fail("Parsing empty string faulted"); + if (XML_Parse(parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) + fail("Parsing final empty string not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_NO_ELEMENTS) + fail("Parsing final empty string faulted for wrong reason"); + + /* Now try with valid text before the empty end */ + XML_ParserReset(parser, NULL); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + if (XML_Parse(parser, NULL, 0, XML_TRUE) == XML_STATUS_ERROR) + fail("Parsing final empty string faulted"); + + /* Now try with invalid text before the empty end */ + XML_ParserReset(parser, NULL); + if (_XML_Parse_SINGLE_BYTES(parser, partial, strlen(partial), + XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + if (XML_Parse(parser, NULL, 0, XML_TRUE) != XML_STATUS_ERROR) + fail("Parsing final incomplete empty string not faulted"); +} +END_TEST + +/* Test odd corners of the XML_GetBuffer interface */ +START_TEST(test_get_buffer_1) +{ + const char *text = + "\n\n" is not one of them, so the parser should raise an + * error on encountering it. + */ +static int XMLCALL +external_entity_param(XML_Parser parser, + const XML_Char *context, + const XML_Char *UNUSED_P(base), + const XML_Char *systemId, + const XML_Char *UNUSED_P(publicId)) +{ + const char *text1 = + "\n" + "\n" + "\n" + "%e1;\n"; + const char *text2 = + "\n" + "\n"; + XML_Parser ext_parser; + + if (systemId == NULL) + return XML_STATUS_OK; + + ext_parser = XML_ExternalEntityParserCreate(parser, context, NULL); + if (ext_parser == NULL) + fail("Could not create external entity parser"); + + if (!strcmp(systemId, "004-1.ent")) { + if (_XML_Parse_SINGLE_BYTES(ext_parser, text1, strlen(text1), + XML_TRUE) != XML_STATUS_ERROR) + fail("Inner DTD with invalid tag not rejected"); + if (XML_GetErrorCode(ext_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) + xml_failure(ext_parser); + } + else if (!strcmp(systemId, "004-2.ent")) { + if (_XML_Parse_SINGLE_BYTES(ext_parser, text2, strlen(text2), + XML_TRUE) != XML_STATUS_ERROR) + fail("Invalid tag in external param not rejected"); + if (XML_GetErrorCode(ext_parser) != XML_ERROR_SYNTAX) + xml_failure(ext_parser); + } else { + fail("Unknown system ID"); + } + + return XML_STATUS_ERROR; +} + +START_TEST(test_invalid_tag_in_dtd) +{ + const char *text = + "\n" + "\n"; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(parser, external_entity_param); + expect_failure(text, XML_ERROR_EXTERNAL_ENTITY_HANDLING, + "Invalid tag IN DTD external param not rejected"); +} +END_TEST + + +/* + * Namespaces tests. + */ + +static void +namespace_setup(void) +{ + parser = XML_ParserCreateNS(NULL, ' '); + if (parser == NULL) + fail("Parser not created."); +} + +static void +namespace_teardown(void) +{ + basic_teardown(); +} + +/* Check that an element name and attribute name match the expected values. + The expected values are passed as an array reference of string pointers + provided as the userData argument; the first is the expected + element name, and the second is the expected attribute name. +*/ +static int triplet_count = 0; + +static void XMLCALL +triplet_start_checker(void *userData, const XML_Char *name, + const XML_Char **atts) +{ + char **elemstr = (char **)userData; + char buffer[1024]; + if (strcmp(elemstr[0], name) != 0) { + sprintf(buffer, "unexpected start string: '%s'", name); + fail(buffer); + } + if (strcmp(elemstr[1], atts[0]) != 0) { + sprintf(buffer, "unexpected attribute string: '%s'", atts[0]); + fail(buffer); + } + triplet_count++; +} + +/* Check that the element name passed to the end-element handler matches + the expected value. The expected value is passed as the first element + in an array of strings passed as the userData argument. +*/ +static void XMLCALL +triplet_end_checker(void *userData, const XML_Char *name) +{ + char **elemstr = (char **)userData; + if (strcmp(elemstr[0], name) != 0) { + char buffer[1024]; + sprintf(buffer, "unexpected end string: '%s'", name); + fail(buffer); + } + triplet_count++; +} + +START_TEST(test_return_ns_triplet) +{ + const char *text = + ""; + const char *epilog = ""; + const char *elemstr[] = { + "http://expat.sf.net/ e foo", + "http://expat.sf.net/ a bar" + }; + XML_SetReturnNSTriplet(parser, XML_TRUE); + XML_SetUserData(parser, elemstr); + XML_SetElementHandler(parser, triplet_start_checker, + triplet_end_checker); + XML_SetNamespaceDeclHandler(parser, + dummy_start_namespace_decl_handler, + dummy_end_namespace_decl_handler); + triplet_count = 0; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_FALSE) == XML_STATUS_ERROR) + xml_failure(parser); + if (triplet_count != 1) + fail("triplet_start_checker not invoked"); + /* Check that unsetting "return triplets" fails while still parsing */ + XML_SetReturnNSTriplet(parser, XML_FALSE); + if (_XML_Parse_SINGLE_BYTES(parser, epilog, strlen(epilog), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + if (triplet_count != 2) + fail("triplet_end_checker not invoked"); +} +END_TEST + +static void XMLCALL +overwrite_start_checker(void *userData, const XML_Char *name, + const XML_Char **atts) +{ + CharData *storage = (CharData *) userData; + CharData_AppendString(storage, "start "); + CharData_AppendXMLChars(storage, name, -1); + while (*atts != NULL) { + CharData_AppendString(storage, "\nattribute "); + CharData_AppendXMLChars(storage, *atts, -1); + atts += 2; + } + CharData_AppendString(storage, "\n"); +} + +static void XMLCALL +overwrite_end_checker(void *userData, const XML_Char *name) +{ + CharData *storage = (CharData *) userData; + CharData_AppendString(storage, "end "); + CharData_AppendXMLChars(storage, name, -1); + CharData_AppendString(storage, "\n"); +} + +static void +run_ns_tagname_overwrite_test(const char *text, const char *result) +{ + CharData storage; + CharData_Init(&storage); + XML_SetUserData(parser, &storage); + XML_SetElementHandler(parser, + overwrite_start_checker, overwrite_end_checker); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); + CharData_CheckString(&storage, result); +} + +/* Regression test for SF bug #566334. */ +START_TEST(test_ns_tagname_overwrite) +{ + const char *text = + "\n" + " \n" + " \n" + ""; + const char *result = + "start http://xml.libexpat.org/ e\n" + "start http://xml.libexpat.org/ f\n" + "attribute http://xml.libexpat.org/ attr\n" + "end http://xml.libexpat.org/ f\n" + "start http://xml.libexpat.org/ g\n" + "attribute http://xml.libexpat.org/ attr2\n" + "end http://xml.libexpat.org/ g\n" + "end http://xml.libexpat.org/ e\n"; + run_ns_tagname_overwrite_test(text, result); +} +END_TEST + +/* Regression test for SF bug #566334. */ +START_TEST(test_ns_tagname_overwrite_triplet) +{ + const char *text = + "\n" + " \n" + " \n" + ""; const char *result = "start http://xml.libexpat.org/ e n\n" "start http://xml.libexpat.org/ f n\n" @@ -1392,75 +2560,648 @@ START_TEST(test_ns_tagname_overwrite_triplet) "end http://xml.libexpat.org/ g n\n" "end http://xml.libexpat.org/ e n\n"; XML_SetReturnNSTriplet(parser, XML_TRUE); - run_ns_tagname_overwrite_test(text, result); + run_ns_tagname_overwrite_test(text, result); +} +END_TEST + + +/* Regression test for SF bug #620343. */ +static void XMLCALL +start_element_fail(void *UNUSED_P(userData), + const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts)) +{ + /* We should never get here. */ + fail("should never reach start_element_fail()"); +} + +static void XMLCALL +start_ns_clearing_start_element(void *userData, + const XML_Char *UNUSED_P(prefix), + const XML_Char *UNUSED_P(uri)) +{ + XML_SetStartElementHandler((XML_Parser) userData, NULL); +} + +START_TEST(test_start_ns_clears_start_element) +{ + /* This needs to use separate start/end tags; using the empty tag + syntax doesn't cause the problematic path through Expat to be + taken. + */ + const char *text = ""; + + XML_SetStartElementHandler(parser, start_element_fail); + XML_SetStartNamespaceDeclHandler(parser, start_ns_clearing_start_element); + XML_SetEndNamespaceDeclHandler(parser, dummy_end_namespace_decl_handler); + XML_UseParserAsHandlerArg(parser); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + +/* Regression test for SF bug #616863. */ +static int XMLCALL +external_entity_handler(XML_Parser parser, + const XML_Char *context, + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) +{ + intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser); + const char *text; + XML_Parser p2; + + if (callno == 1) + text = ("\n" + "\n" + "\n"); + else + text = ("" + ""); + + XML_SetUserData(parser, (void *) callno); + p2 = XML_ExternalEntityParserCreate(parser, context, NULL); + if (_XML_Parse_SINGLE_BYTES(p2, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) { + xml_failure(p2); + return 0; + } + XML_ParserFree(p2); + return 1; +} + +START_TEST(test_default_ns_from_ext_subset_and_ext_ge) +{ + const char *text = + "\n" + "\n" + "]>\n" + "\n" + "&en;\n" + ""; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(parser, external_entity_handler); + /* We actually need to set this handler to tickle this bug. */ + XML_SetStartElementHandler(parser, dummy_start_element); + XML_SetUserData(parser, NULL); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + +/* Regression test #1 for SF bug #673791. */ +START_TEST(test_ns_prefix_with_empty_uri_1) +{ + const char *text = + "\n" + " \n" + ""; + + expect_failure(text, + XML_ERROR_UNDECLARING_PREFIX, + "Did not report re-setting namespace" + " URI with prefix to ''."); +} +END_TEST + +/* Regression test #2 for SF bug #673791. */ +START_TEST(test_ns_prefix_with_empty_uri_2) +{ + const char *text = + "\n" + ""; + + expect_failure(text, + XML_ERROR_UNDECLARING_PREFIX, + "Did not report setting namespace URI with prefix to ''."); +} +END_TEST + +/* Regression test #3 for SF bug #673791. */ +START_TEST(test_ns_prefix_with_empty_uri_3) +{ + const char *text = + "\n" + " \n" + "]>\n" + ""; + + expect_failure(text, + XML_ERROR_UNDECLARING_PREFIX, + "Didn't report attr default setting NS w/ prefix to ''."); +} +END_TEST + +/* Regression test #4 for SF bug #673791. */ +START_TEST(test_ns_prefix_with_empty_uri_4) +{ + const char *text = + "\n" + " \n" + "]>\n" + ""; + /* Packaged info expected by the end element handler; + the weird structuring lets us re-use the triplet_end_checker() + function also used for another test. */ + const char *elemstr[] = { + "http://xml.libexpat.org/ doc prefix" + }; + XML_SetReturnNSTriplet(parser, XML_TRUE); + XML_SetUserData(parser, elemstr); + XML_SetEndElementHandler(parser, triplet_end_checker); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + +START_TEST(test_ns_default_with_empty_uri) +{ + const char *text = + "\n" + " \n" + ""; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); +} +END_TEST + +/* Regression test for SF bug #692964: two prefixes for one namespace. */ +START_TEST(test_ns_duplicate_attrs_diff_prefixes) +{ + const char *text = + ""; + expect_failure(text, + XML_ERROR_DUPLICATE_ATTRIBUTE, + "did not report multiple attributes with same URI+name"); +} +END_TEST + +/* Regression test for SF bug #695401: unbound prefix. */ +START_TEST(test_ns_unbound_prefix_on_attribute) +{ + const char *text = ""; + expect_failure(text, + XML_ERROR_UNBOUND_PREFIX, + "did not report unbound prefix on attribute"); +} +END_TEST + +/* Regression test for SF bug #695401: unbound prefix. */ +START_TEST(test_ns_unbound_prefix_on_element) +{ + const char *text = ""; + expect_failure(text, + XML_ERROR_UNBOUND_PREFIX, + "did not report unbound prefix on element"); +} +END_TEST + +/* Test that the parsing status is correctly reset by XML_ParserReset(). + * We usE test_return_ns_triplet() for our example parse to improve + * coverage of tidying up code executed. + */ +START_TEST(test_ns_parser_reset) +{ + XML_ParsingStatus status; + + XML_GetParsingStatus(parser, &status); + if (status.parsing != XML_INITIALIZED) + fail("parsing status doesn't start INITIALIZED"); + test_return_ns_triplet(); + XML_GetParsingStatus(parser, &status); + if (status.parsing != XML_FINISHED) + fail("parsing status doesn't end FINISHED"); + XML_ParserReset(parser, NULL); + XML_GetParsingStatus(parser, &status); + if (status.parsing != XML_INITIALIZED) + fail("parsing status doesn't reset to INITIALIZED"); +} +END_TEST + +/* Control variable; the number of times duff_allocator() will successfully allocate */ +static unsigned int allocation_count = 0; + +/* Crocked allocator for allocation failure tests */ +static void *duff_allocator(size_t size) +{ + if (allocation_count == 0) + return NULL; + allocation_count--; + return malloc(size); +} + +/* Test that a failure to allocate the parser structure fails gracefully */ +START_TEST(test_misc_alloc_create_parser) +{ + XML_Memory_Handling_Suite memsuite = { duff_allocator, realloc, free }; + unsigned int i; + + /* Something this simple shouldn't need more than 10 allocations */ + for (i = 0; i < 10; i++) + { + allocation_count = i; + parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); + if (parser != NULL) + break; + } + if (i == 0) + fail("Parser unexpectedly ignored failing allocator"); + else if (i == 10) + fail("Parser not created with allocation count 10"); +} +END_TEST + +/* Test memory allocation failures for a parser with an encoding */ +START_TEST(test_misc_alloc_create_parser_with_encoding) +{ + XML_Memory_Handling_Suite memsuite = { duff_allocator, realloc, free }; + unsigned int i; + + /* Try several levels of allocation */ + for (i = 0; i < 10; i++) { + allocation_count = i; + parser = XML_ParserCreate_MM("us-ascii", &memsuite, NULL); + if (parser != NULL) + break; + } + if (i == 0) + fail("Parser ignored failing allocator"); + else if (i == 10) + fail("Parser not created with allocation count 10"); +} +END_TEST + +/* Test the effects of allocation failure in simple namespace parsing. + * Based on test_ns_default_with_empty_uri() + */ +START_TEST(test_misc_alloc_ns) +{ + XML_Memory_Handling_Suite memsuite = { duff_allocator, realloc, free }; + const char *text = + "\n" + " \n" + ""; + unsigned int i; + int repeated = 0; + XML_Char ns_sep[2] = { ' ', '\0' }; + + allocation_count = 10000; + parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep); + if (parser == NULL) { + fail("Parser not created"); + } else { + for (i = 0; i < 10; i++) { + /* Repeat some tests with the same allocation count to + * catch cached allocations not freed by XML_ParserReset() + */ + if (repeated < 2 && i == 3) { + i--; + repeated++; + } + if (repeated == 2 && i == 5) { + i = 3; + repeated++; + } + allocation_count = i; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + break; + XML_ParserReset(parser, NULL); + } + if (i == 0) + fail("Parsing worked despite failing allocations"); + else if (i == 10) + fail("Parsing failed even at allocation count 10"); + } +} +END_TEST + +/* Test XML_ParseBuffer interface with namespace and a dicky allocator */ +START_TEST(test_misc_alloc_ns_parse_buffer) +{ + XML_Memory_Handling_Suite memsuite = { duff_allocator, realloc, free }; + XML_Char ns_sep[2] = { ' ', '\0' }; + const char *text = "Hello"; + void *buffer; + + /* Make sure the basic parser is allocated */ + allocation_count = 10000; + parser = XML_ParserCreate_MM(NULL, &memsuite, ns_sep); + if (parser == NULL) + fail("Parser not created"); + + /* Try a parse before the start of the world */ + /* (Exercises new code path) */ + allocation_count = 0; + if (XML_ParseBuffer(parser, 0, XML_FALSE) != XML_STATUS_ERROR) + fail("Pre-init XML_ParseBuffer not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_NO_MEMORY) + fail("Pre-init XML_ParseBuffer faulted for wrong reason"); + + /* Now with actual memory allocation */ + allocation_count = 10000; + if (XML_ParseBuffer(parser, 0, XML_FALSE) != XML_STATUS_OK) + xml_failure(parser); + + /* Check that resuming an unsuspended parser is faulted */ + if (XML_ResumeParser(parser) != XML_STATUS_ERROR) + fail("Resuming unsuspended parser not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_NOT_SUSPENDED) + xml_failure(parser); + + /* Get the parser into suspended state */ + XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler); + resumable = XML_TRUE; + buffer = XML_GetBuffer(parser, strlen(text)); + if (buffer == NULL) + fail("Could not acquire parse buffer"); + memcpy(buffer, text, strlen(text)); + if (XML_ParseBuffer(parser, strlen(text), + XML_TRUE) != XML_STATUS_SUSPENDED) + xml_failure(parser); + if (XML_GetErrorCode(parser) != XML_ERROR_NONE) + xml_failure(parser); + if (XML_ParseBuffer(parser, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + fail("Suspended XML_ParseBuffer not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_SUSPENDED) + xml_failure(parser); + if (XML_GetBuffer(parser, strlen(text)) != NULL) + fail("Suspended XML_GetBuffer not faulted"); + + /* Get it going again and complete the world */ + XML_SetCharacterDataHandler(parser, NULL); + if (XML_ResumeParser(parser) != XML_STATUS_OK) + xml_failure(parser); + if (XML_ParseBuffer(parser, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + fail("Post-finishing XML_ParseBuffer not faulted"); + if (XML_GetErrorCode(parser) != XML_ERROR_FINISHED) + xml_failure(parser); + if (XML_GetBuffer(parser, strlen(text)) != NULL) + fail("Post-finishing XML_GetBuffer not faulted"); +} +END_TEST + +/* Test that freeing a NULL parser doesn't cause an explosion. + * (Not actually tested anywhere else) + */ +START_TEST(test_misc_null_parser) +{ + XML_ParserFree(NULL); +} +END_TEST + +/* Test that XML_ErrorString rejects out-of-range codes */ +START_TEST(test_misc_error_string) +{ + if (XML_ErrorString((enum XML_Error)-1) != NULL) + fail("Negative error code not rejected"); + if (XML_ErrorString((enum XML_Error)100) != NULL) + fail("Large error code not rejected"); +} +END_TEST + +/* Test the version information is consistent */ +START_TEST(test_misc_version) +{ + XML_Expat_Version version_struct = XML_ExpatVersionInfo(); + const XML_LChar *version_text = XML_ExpatVersion(); + long value; + const char *p; + char *endp; + + if (version_text == NULL) + fail("Could not obtain version text"); + for (p = version_text; *p != '\0'; p++) + if (isdigit(*p)) + break; + if (*p == '\0') + fail("No numbers in version text"); + value = strtoul(p, &endp, 10); + if (*endp != '.') + fail("Major version conversion from text failed"); + if (value != version_struct.major) + fail("Major version mismatch"); + p = endp + 1; + value = strtoul(p, &endp, 10); + if (*endp != '.') + fail("Minor version conversion from text failed"); + if (value != version_struct.minor) + fail("Minor version mismatch"); + p = endp + 1; + value = strtoul(p, &endp, 10); + if (*endp != '\0') + fail("Micro version conversion from text failed"); + if (value != version_struct.micro) + fail("Micro version mismatch"); +} +END_TEST + +/* Regression test for GitHub Issue #17: memory leak parsing attribute + * values with mixed bound and unbound namespaces. + */ +START_TEST(test_misc_attribute_leak) +{ + const char *text = ""; + XML_Memory_Handling_Suite memsuite = { + tracking_malloc, + tracking_realloc, + tracking_free + }; + + parser = XML_ParserCreate_MM("UTF-8", &memsuite, "\n"); + expect_failure(text, XML_ERROR_UNBOUND_PREFIX, + "Unbound prefixes not found"); + XML_ParserFree(parser); + /* Prevent the teardown trying to double free */ + parser = NULL; + + if (!tracking_report()) + fail("Memory leak found"); } END_TEST -/* Regression test for SF bug #620343. */ -static void XMLCALL -start_element_fail(void *UNUSED_P(userData), - const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts)) +static void +alloc_setup(void) { - /* We should never get here. */ - fail("should never reach start_element_fail()"); + XML_Memory_Handling_Suite memsuite = { duff_allocator, realloc, free }; + + /* Ensure the parser creation will go through */ + allocation_count = 10000; + parser = XML_ParserCreate_MM(NULL, &memsuite, NULL); + if (parser == NULL) + fail("Parser not created"); } -static void XMLCALL -start_ns_clearing_start_element(void *userData, - const XML_Char *UNUSED_P(prefix), - const XML_Char *UNUSED_P(uri)) +static void +alloc_teardown(void) { - XML_SetStartElementHandler((XML_Parser) userData, NULL); + basic_teardown(); } -START_TEST(test_start_ns_clears_start_element) +static int XMLCALL +external_entity_duff_loader(XML_Parser parser, + const XML_Char *context, + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) { - /* This needs to use separate start/end tags; using the empty tag - syntax doesn't cause the problematic path through Expat to be - taken. - */ - const char *text = ""; + XML_Parser new_parser; + unsigned int i; + + /* Try a few different allocation levels */ + for (i = 0; i < 10; i++) + { + allocation_count = i; + new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); + if (new_parser != NULL) + { + XML_ParserFree(new_parser); + break; + } + } + if (i == 0) + fail("External parser creation ignored failing allocator"); + else if (i == 10) + fail("Extern parser not created with allocation count 10"); - XML_SetStartElementHandler(parser, start_element_fail); - XML_SetStartNamespaceDeclHandler(parser, start_ns_clearing_start_element); - XML_UseParserAsHandlerArg(parser); - if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) - xml_failure(parser); + /* Make sure other random allocation doesn't now fail */ + allocation_count = 10000; + + /* Make sure the failure code path is executed too */ + return XML_STATUS_ERROR; +} + +/* Test that external parser creation running out of memory is + * correctly reported. Based on the external entity test cases. + */ +START_TEST(test_alloc_create_external_parser) +{ + const char *text = + "\n" + "\n" + "&entity;"; + char foo_text[] = + ""; + + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetUserData(parser, foo_text); + XML_SetExternalEntityRefHandler(parser, + external_entity_duff_loader); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) { + fail("External parser allocator returned success incorrectly"); + } } END_TEST -/* Regression test for SF bug #616863. */ static int XMLCALL -external_entity_handler(XML_Parser parser, - const XML_Char *context, - const XML_Char *UNUSED_P(base), - const XML_Char *UNUSED_P(systemId), - const XML_Char *UNUSED_P(publicId)) +external_entity_null_loader(XML_Parser UNUSED_P(parser), + const XML_Char *UNUSED_P(context), + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) { - intptr_t callno = 1 + (intptr_t)XML_GetUserData(parser); + return XML_STATUS_OK; +} + +/* More external parser memory allocation testing */ +START_TEST(test_alloc_run_external_parser) +{ + const char *text = + "\n" + "\n" + "&entity;"; + char foo_text[] = + ""; + unsigned int i; + + for (i = 0; i < 10; i++) { + XML_SetParamEntityParsing(parser, + XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetUserData(parser, foo_text); + XML_SetExternalEntityRefHandler(parser, + external_entity_null_loader); + allocation_count = i; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + break; + /* Re-use the parser */ + XML_ParserReset(parser, NULL); + } + if (i == 0) + fail("Parsing ignored failing allocator"); + else if (i == 10) + fail("Parsing failed with allocation count 10"); +} +END_TEST + + +static int XMLCALL +external_entity_dbl_handler(XML_Parser parser, + const XML_Char *context, + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) +{ + intptr_t callno = (intptr_t)XML_GetUserData(parser); const char *text; - XML_Parser p2; + XML_Parser new_parser; + int i; - if (callno == 1) + if (callno == 0) { + /* First time through, check how many calls to malloc occur */ text = ("\n" "\n" "\n"); - else + allocation_count = 10000; + new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); + if (new_parser == NULL) { + fail("Unable to allocate first external parser"); + return 0; + } + /* Stash the number of calls in the user data */ + XML_SetUserData(parser, (void *)(intptr_t)(10000 - allocation_count)); + } else { text = ("" ""); + /* Try at varying levels to exercise more code paths */ + for (i = 0; i < 20; i++) { + allocation_count = callno + i; + new_parser = XML_ExternalEntityParserCreate(parser, + context, + NULL); + if (new_parser != NULL) + break; + } + if (i == 0) { + fail("Second external parser unexpectedly created"); + XML_ParserFree(new_parser); + return 0; + } + else if (i == 20) { + fail("Second external parser not created"); + return 0; + } + } - XML_SetUserData(parser, (void *) callno); - p2 = XML_ExternalEntityParserCreate(parser, context, NULL); - if (_XML_Parse_SINGLE_BYTES(p2, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) { - xml_failure(p2); + allocation_count = 10000; + if (_XML_Parse_SINGLE_BYTES(new_parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) { + xml_failure(new_parser); return 0; } - XML_ParserFree(p2); + XML_ParserFree(new_parser); return 1; } -START_TEST(test_default_ns_from_ext_subset_and_ext_ge) +/* Test that running out of memory in dtdCopy is correctly reported. + * Based on test_default_ns_from_ext_subset_and_ext_ge() + */ +START_TEST(test_alloc_dtd_copy_default_atts) { const char *text = "\n" @@ -1472,139 +3213,265 @@ START_TEST(test_default_ns_from_ext_subset_and_ext_ge) ""; XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); - XML_SetExternalEntityRefHandler(parser, external_entity_handler); - /* We actually need to set this handler to tickle this bug. */ - XML_SetStartElementHandler(parser, dummy_start_element); + XML_SetExternalEntityRefHandler(parser, + external_entity_dbl_handler); XML_SetUserData(parser, NULL); if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) xml_failure(parser); } END_TEST -/* Regression test #1 for SF bug #673791. */ -START_TEST(test_ns_prefix_with_empty_uri_1) + +static int XMLCALL +external_entity_dbl_handler_2(XML_Parser parser, + const XML_Char *context, + const XML_Char *UNUSED_P(base), + const XML_Char *UNUSED_P(systemId), + const XML_Char *UNUSED_P(publicId)) { - const char *text = - "\n" - " \n" - ""; + intptr_t callno = (intptr_t)XML_GetUserData(parser); + const char *text; + XML_Parser new_parser; + int i; - expect_failure(text, - XML_ERROR_UNDECLARING_PREFIX, - "Did not report re-setting namespace" - " URI with prefix to ''."); + if (callno == 0) { + /* Try different allocation levels for whole exercise */ + text = ("\n" + "\n" + "\n"); + XML_SetUserData(parser, (void *)(intptr_t)1); + for (i = 0; i < 20; i++) { + allocation_count = i; + new_parser = XML_ExternalEntityParserCreate(parser, + context, + NULL); + if (new_parser == NULL) + continue; + if (_XML_Parse_SINGLE_BYTES(new_parser, text, strlen(text), + XML_TRUE) != XML_STATUS_ERROR) + break; + XML_ParserFree(new_parser); + } + + /* Ensure future allocations will be well */ + allocation_count = 10000; + if (i == 0) { + fail("first external parser unexpectedly created"); + XML_ParserFree(new_parser); + return 0; + } + else if (i == 20) { + fail("first external parser not allocated with count 20"); + return 0; + } + } else { + /* Just run through once */ + text = ("" + ""); + allocation_count = 10000; + new_parser = XML_ExternalEntityParserCreate(parser, context, NULL); + if (new_parser == NULL) { + fail("Unable to create second external parser"); + return 0; + } + if (_XML_Parse_SINGLE_BYTES(new_parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) { + xml_failure(new_parser); + XML_ParserFree(new_parser); + return 0; + } + } + XML_ParserFree(new_parser); + return 1; } -END_TEST -/* Regression test #2 for SF bug #673791. */ -START_TEST(test_ns_prefix_with_empty_uri_2) +/* Test more external entity allocation failure paths */ +START_TEST(test_alloc_external_entity) { const char *text = "\n" - ""; + "\n" + "]>\n" + "\n" + "&en;\n" + ""; - expect_failure(text, - XML_ERROR_UNDECLARING_PREFIX, - "Did not report setting namespace URI with prefix to ''."); + XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS); + XML_SetExternalEntityRefHandler(parser, + external_entity_dbl_handler_2); + XML_SetUserData(parser, NULL); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) == XML_STATUS_ERROR) + xml_failure(parser); } END_TEST -/* Regression test #3 for SF bug #673791. */ -START_TEST(test_ns_prefix_with_empty_uri_3) + +static int XMLCALL +unknown_released_encoding_handler(void *UNUSED_P(data), + const XML_Char *encoding, + XML_Encoding *info) { - const char *text = - "\n" - " \n" - "]>\n" - ""; + if (!strcmp(encoding, "unsupported-encoding")) { + int i; - expect_failure(text, - XML_ERROR_UNDECLARING_PREFIX, - "Didn't report attr default setting NS w/ prefix to ''."); + for (i = 0; i < 256; i++) + info->map[i] = i; + info->data = NULL; + info->convert = NULL; + info->release = dummy_release; + return XML_STATUS_OK; + } + return XML_STATUS_ERROR; } -END_TEST -/* Regression test #4 for SF bug #673791. */ -START_TEST(test_ns_prefix_with_empty_uri_4) +/* Test the effects of allocation failure in internal entities. + * Based on test_unknown_encoding_internal_entity + */ +START_TEST(test_alloc_internal_entity) { const char *text = - "\n" - " \n" - "]>\n" - ""; - /* Packaged info expected by the end element handler; - the weird structuring lets us re-use the triplet_end_checker() - function also used for another test. */ - const char *elemstr[] = { - "http://xml.libexpat.org/ doc prefix" - }; - XML_SetReturnNSTriplet(parser, XML_TRUE); - XML_SetUserData(parser, elemstr); - XML_SetEndElementHandler(parser, triplet_end_checker); - if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) - xml_failure(parser); + "\n" + "]>\n" + ""; + unsigned int i; + int repeated = 0; + + for (i = 0; i < 10; i++) { + /* Again, repeat some counts to account for caching */ + if (repeated < 2 && i == 2) { + i--; + repeated++; + } + XML_SetUnknownEncodingHandler(parser, + unknown_released_encoding_handler, + NULL); + allocation_count = i; + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR) + break; + XML_ParserReset(parser, NULL); + } + if (i == 0) + fail("Internal entity worked despite failing allocations"); + else if (i == 10) + fail("Internal entity failed at allocation count 10"); } END_TEST -START_TEST(test_ns_default_with_empty_uri) -{ - const char *text = - "\n" - " \n" - ""; - if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) - xml_failure(parser); -} -END_TEST -/* Regression test for SF bug #692964: two prefixes for one namespace. */ -START_TEST(test_ns_duplicate_attrs_diff_prefixes) +/* Test the robustness against allocation failure of element handling + * Based on test_dtd_default_handling(). + */ +START_TEST(test_alloc_dtd_default_handling) { const char *text = - ""; - expect_failure(text, - XML_ERROR_DUPLICATE_ATTRIBUTE, - "did not report multiple attributes with same URI+name"); + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "]>"; + const char *expected = "\n\n\n\n\n\n\n"; + CharData storage; + int i; + int repeat = 0; + + for (i = 0; i < 10; i++) { + /* Repeat some counts to catch cached allocations */ + if ((repeat < 4 && i == 2) || + (repeat == 4 && i == 3)) { + i--; + repeat++; + } + allocation_count = i; + XML_SetDefaultHandler(parser, accumulate_characters); + XML_SetDoctypeDeclHandler(parser, + dummy_start_doctype_handler, + dummy_end_doctype_handler); + XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler); + XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler); + XML_SetElementDeclHandler(parser, dummy_element_decl_handler); + XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler); + XML_SetProcessingInstructionHandler(parser, dummy_pi_handler); + XML_SetCommentHandler(parser, dummy_comment_handler); + XML_SetCdataSectionHandler(parser, + dummy_start_cdata_handler, + dummy_end_cdata_handler); + XML_SetUnparsedEntityDeclHandler( + parser, + dummy_unparsed_entity_decl_handler); + CharData_Init(&storage); + XML_SetUserData(parser, &storage); + XML_SetCharacterDataHandler(parser, accumulate_characters); + if (_XML_Parse_SINGLE_BYTES(parser, text, strlen(text), + XML_TRUE) != XML_STATUS_ERROR) + break; + XML_ParserReset(parser, NULL); + } + if (i == 0) { + fail("Default DTD parsed despite allocation failures"); + } else if (i == 10) { + fail("Default DTD not parsed with alloc count 10"); + } else { + CharData_CheckXMLChars(&storage, expected); + } } END_TEST -/* Regression test for SF bug #695401: unbound prefix. */ -START_TEST(test_ns_unbound_prefix_on_attribute) +/* Test robustness of XML_SetEncoding() with a failing allocator */ +START_TEST(test_alloc_explicit_encoding) { - const char *text = ""; - expect_failure(text, - XML_ERROR_UNBOUND_PREFIX, - "did not report unbound prefix on attribute"); + int i; + + for (i = 0; i < 5; i++) { + allocation_count = i; + if (XML_SetEncoding(parser, "us-ascii") == XML_STATUS_OK) + break; + } + if (i == 0) + fail("Encoding set despite failing allocator"); + else if (i == 5) + fail("Encoding not set at allocation count 5"); } END_TEST -/* Regression test for SF bug #695401: unbound prefix. */ -START_TEST(test_ns_unbound_prefix_on_element) +/* Test robustness of XML_SetBase against a failing allocator */ +START_TEST(test_alloc_set_base) { - const char *text = ""; - expect_failure(text, - XML_ERROR_UNBOUND_PREFIX, - "did not report unbound prefix on element"); + const XML_Char *new_base = "/local/file/name.xml"; + int i; + + for (i = 0; i < 5; i++) { + allocation_count = i; + if (XML_SetBase(parser, new_base) == XML_STATUS_OK) + break; + } + if (i == 0) + fail("Base set despite failing allocator"); + else if (i == 5) + fail("Base not set with allocation count 5"); } END_TEST + static Suite * make_suite(void) { Suite *s = suite_create("basic"); TCase *tc_basic = tcase_create("basic tests"); TCase *tc_namespace = tcase_create("XML namespaces"); + TCase *tc_misc = tcase_create("miscellaneous tests"); + TCase *tc_alloc = tcase_create("allocation tests"); suite_add_tcase(s, tc_basic); tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown); tcase_add_test(tc_basic, test_nul_byte); tcase_add_test(tc_basic, test_u0000_char); + tcase_add_test(tc_basic, test_siphash_self); + tcase_add_test(tc_basic, test_siphash_spec); tcase_add_test(tc_basic, test_bom_utf8); tcase_add_test(tc_basic, test_bom_utf16_be); tcase_add_test(tc_basic, test_bom_utf16_le); @@ -1631,11 +3498,14 @@ make_suite(void) tcase_add_test(tc_basic, test_attr_whitespace_normalization); tcase_add_test(tc_basic, test_xmldecl_misplaced); tcase_add_test(tc_basic, test_unknown_encoding_internal_entity); + tcase_add_test(tc_basic, test_unrecognised_encoding_internal_entity); tcase_add_test(tc_basic, test_wfc_undeclared_entity_unread_external_subset); tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset); tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone); tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset); + tcase_add_test(tc_basic, test_not_standalone_handler_reject); + tcase_add_test(tc_basic, test_not_standalone_handler_accept); tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset_standalone); tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs); @@ -1645,9 +3515,31 @@ make_suite(void) tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces); tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls); tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls); + tcase_add_test(tc_basic, test_repeated_stop_parser_between_char_data_calls); tcase_add_test(tc_basic, test_good_cdata_ascii); tcase_add_test(tc_basic, test_good_cdata_utf16); tcase_add_test(tc_basic, test_bad_cdata); + tcase_add_test(tc_basic, test_memory_allocation); + tcase_add_test(tc_basic, test_default_current); + tcase_add_test(tc_basic, test_dtd_elements); + tcase_add_test(tc_basic, test_set_foreign_dtd); + tcase_add_test(tc_basic, test_set_base); + tcase_add_test(tc_basic, test_attributes); + tcase_add_test(tc_basic, test_reset_in_entity); + tcase_add_test(tc_basic, test_resume_invalid_parse); + tcase_add_test(tc_basic, test_resume_resuspended); + tcase_add_test(tc_basic, test_subordinate_reset); + tcase_add_test(tc_basic, test_subordinate_suspend); + tcase_add_test(tc_basic, test_explicit_encoding); + tcase_add_test(tc_basic, test_user_parameters); + tcase_add_test(tc_basic, test_ext_entity_ref_parameter); + tcase_add_test(tc_basic, test_empty_parse); + tcase_add_test(tc_basic, test_get_buffer_1); + tcase_add_test(tc_basic, test_get_buffer_2); + tcase_add_test(tc_basic, test_byte_info_at_end); + tcase_add_test(tc_basic, test_byte_info_at_error); + tcase_add_test(tc_basic, test_byte_info_at_cdata); + tcase_add_test(tc_basic, test_invalid_tag_in_dtd); suite_add_tcase(s, tc_namespace); tcase_add_checked_fixture(tc_namespace, @@ -1665,6 +3557,29 @@ make_suite(void) tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes); tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute); tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element); + tcase_add_test(tc_namespace, test_ns_parser_reset); + + suite_add_tcase(s, tc_misc); + tcase_add_checked_fixture(tc_misc, NULL, basic_teardown); + tcase_add_test(tc_misc, test_misc_alloc_create_parser); + tcase_add_test(tc_misc, test_misc_alloc_create_parser_with_encoding); + tcase_add_test(tc_misc, test_misc_alloc_ns); + tcase_add_test(tc_misc, test_misc_null_parser); + tcase_add_test(tc_misc, test_misc_alloc_ns_parse_buffer); + tcase_add_test(tc_misc, test_misc_error_string); + tcase_add_test(tc_misc, test_misc_version); + tcase_add_test(tc_misc, test_misc_attribute_leak); + + suite_add_tcase(s, tc_alloc); + tcase_add_checked_fixture(tc_alloc, alloc_setup, alloc_teardown); + tcase_add_test(tc_alloc, test_alloc_create_external_parser); + tcase_add_test(tc_alloc, test_alloc_run_external_parser); + tcase_add_test(tc_alloc, test_alloc_dtd_copy_default_atts); + tcase_add_test(tc_alloc, test_alloc_external_entity); + tcase_add_test(tc_alloc, test_alloc_internal_entity); + tcase_add_test(tc_alloc, test_alloc_dtd_default_handling); + tcase_add_test(tc_alloc, test_alloc_explicit_encoding); + tcase_add_test(tc_alloc, test_alloc_set_base); return s; } diff --git a/modules/expat/tests/runtests.sln b/modules/expat/tests/runtests.sln new file mode 100644 index 00000000..6e07293f --- /dev/null +++ b/modules/expat/tests/runtests.sln @@ -0,0 +1,24 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runtests", "runtests.vcxproj", "{63D6D820-B526-4A5F-9605-9B8551FAC591}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Template|Win32 = Template|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {63D6D820-B526-4A5F-9605-9B8551FAC591}.Debug|Win32.ActiveCfg = Debug|Win32 + {63D6D820-B526-4A5F-9605-9B8551FAC591}.Debug|Win32.Build.0 = Debug|Win32 + {63D6D820-B526-4A5F-9605-9B8551FAC591}.Release|Win32.ActiveCfg = Release|Win32 + {63D6D820-B526-4A5F-9605-9B8551FAC591}.Release|Win32.Build.0 = Release|Win32 + {63D6D820-B526-4A5F-9605-9B8551FAC591}.Template|Win32.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/modules/expat/tests/runtests.vcxproj b/modules/expat/tests/runtests.vcxproj new file mode 100644 index 00000000..ff8f5498 --- /dev/null +++ b/modules/expat/tests/runtests.vcxproj @@ -0,0 +1,140 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + {63D6D820-B526-4A5F-9605-9B8551FAC591} + + + + Application + v120 + false + MultiByte + + + Application + v120 + false + MultiByte + + + + + + + + + + + + + + + .\Release\ + .\Release\ + false + + + .\Debug\ + .\Debug\ + true + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + ..\lib;%(AdditionalIncludeDirectories) + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\Release\ + .\Release\runtests.pch + .\Release\ + .\Release\ + + + .\Release\runtests.tlb + + + 0x1009 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\runtests.bsc + + + true + Console + .\Release\runtests.exe + ..\win32\bin\Release;%(AdditionalLibraryDirectories) + libexpatMT.lib;libexpat.exp;%(AdditionalDependencies) + + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + true + EditAndContinue + ..\lib;%(AdditionalIncludeDirectories) + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\runtests.pch + .\Debug\ + .\Debug\ + EnableFastChecks + + + .\Debug\runtests.tlb + + + 0x1009 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\runtests.bsc + + + true + true + Console + .\Debug\runtests.exe + ..\win32\bin\Debug;%(AdditionalLibraryDirectories) + libexpatMT.lib;libexpat.exp;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/expat/tests/runtests.vcxproj.filters b/modules/expat/tests/runtests.vcxproj.filters new file mode 100644 index 00000000..ca66cb56 --- /dev/null +++ b/modules/expat/tests/runtests.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {a3e83144-e1b8-4d37-853a-793ce2b17b31} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {6a1287d5-359d-4ecb-a1a8-79aec14ad46d} + h;hpp;hxx;hm;inl + + + {75f72e18-16a8-453e-84bc-fe9301b8d5b2} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/modules/expat/tests/xmltest.log.expected b/modules/expat/tests/xmltest.log.expected new file mode 100644 index 00000000..7c92c1d4 --- /dev/null +++ b/modules/expat/tests/xmltest.log.expected @@ -0,0 +1,35 @@ +Output differs: ibm/valid/P02/ibm02v01.xml +Output differs: ibm/valid/P28/ibm28v02.xml +Output differs: ibm/valid/P29/ibm29v01.xml +Output differs: ibm/valid/P29/ibm29v02.xml +Output differs: ibm/valid/P54/ibm54v01.xml +Output differs: ibm/valid/P56/ibm56v08.xml +Output differs: ibm/valid/P57/ibm57v01.xml +Output differs: ibm/valid/P58/ibm58v01.xml +Output differs: ibm/valid/P58/ibm58v02.xml +Output differs: ibm/valid/P70/ibm70v01.xml +Output differs: ibm/valid/P82/ibm82v01.xml +ibm49i02.dtd: No such file or directory +Output differs: ibm/invalid/P58/ibm58i01.xml +Output differs: ibm/invalid/P58/ibm58i02.xml +Output differs: xmltest/valid/sa/069.xml +Output differs: xmltest/valid/sa/076.xml +Output differs: xmltest/valid/sa/090.xml +Output differs: xmltest/valid/sa/091.xml +Output differs: sun/valid/notation01.xml +Output differs: sun/valid/not-sa01.xml +Output differs: sun/valid/not-sa02.xml +Output differs: sun/valid/not-sa03.xml +Output differs: sun/valid/not-sa04.xml +Output differs: sun/valid/sa02.xml +Output differs: sun/valid/sa03.xml +Output differs: sun/valid/sa04.xml +Output differs: sun/valid/sa05.xml +Expected not well-formed: ibm/not-wf/misc/432gewf.xml +Expected not well-formed: xmltest/not-wf/not-sa/005.xml +Expected not well-formed: sun/not-wf/uri01.xml +Expected not well-formed: oasis/p06fail1.xml +Expected not well-formed: oasis/p08fail1.xml +Expected not well-formed: oasis/p08fail2.xml +Passed: 1776 +Failed: 33 diff --git a/modules/expat/tests/xmltest.sh b/modules/expat/tests/xmltest.sh index 64a17eec..e5009328 100755 --- a/modules/expat/tests/xmltest.sh +++ b/modules/expat/tests/xmltest.sh @@ -25,7 +25,7 @@ shopt -s nullglob MYDIR="`dirname \"$0\"`" cd "$MYDIR" MYDIR="`pwd`" -XMLWF="`dirname \"$MYDIR\"`/xmlwf/xmlwf" +XMLWF="${1:-`dirname \"$MYDIR\"`/xmlwf/xmlwf}" # XMLWF=/usr/local/bin/xmlwf TS="$MYDIR" # OUTPUT must terminate with the directory separator. @@ -98,7 +98,8 @@ for xmldir in ibm/valid/P* \ sun/invalid ; do cd "$TS/xmlconf/$xmldir" mkdir -p "$OUTPUT$xmldir" - for xmlfile in *.xml ; do + for xmlfile in $(ls -1 *.xml | sort -d) ; do + [[ -f "$xmlfile" ]] || continue RunXmlwfWF "$xmlfile" "$xmldir/" UpdateStatus $? done diff --git a/modules/expat/win32/.gitignore b/modules/expat/win32/.gitignore new file mode 100644 index 00000000..e7546777 --- /dev/null +++ b/modules/expat/win32/.gitignore @@ -0,0 +1,10 @@ +expat.IAB +expat.IAD +expat.IMB +expat.IMD +expat.PFI +expat.PO +expat.PR +expat.PRI +expat.PS +expat.WK3 diff --git a/modules/expat/win32/MANIFEST.txt b/modules/expat/win32/MANIFEST.txt index b7cd3954..22b61d19 100644 --- a/modules/expat/win32/MANIFEST.txt +++ b/modules/expat/win32/MANIFEST.txt @@ -22,6 +22,4 @@ directory you specified to the installer. formedness checker, and a couple of small sample applications. - \Source\bcb5\ Project files for Borland C++ Builder 5 and BCC 5.5. - diff --git a/modules/expat/win32/README.txt b/modules/expat/win32/README.txt index c58d29ab..462c49b7 100644 --- a/modules/expat/win32/README.txt +++ b/modules/expat/win32/README.txt @@ -1,27 +1,14 @@ -Expat can be built on Windows in three ways: - using MS Visual C++ (6.0 or .NET), Borland C++ Builder 5 or Cygwin. +Expat can be built on Windows in two ways: + using MS Visual Studio .NET or Cygwin. * Cygwin: This follows the Unix build procedures. -* C++ Builder 5: - Possible with make files in the BCB5 subdirectory. - Details can be found in the ReadMe file located there. - -* MS Visual C++ 6: - Based on the workspace file expat.dsw. The related project - files (.dsp) are located in the lib subdirectory. - -* MS Visual Studio .NET 2002, 2003, 2005, 2008, 2010: - The VC++ 6 workspace file (expat.dsw) and project files (.dsp) - can be opened and imported in VS.NET without problems. - Note: Tests have their own *.dsw files. - -* MS Visual Studio 2013 and 2015: +* MS Visual Studio 2013, 2015 and 2017: A solution file for Visual Studio 2013 is provided: expat.sln. The associated project files (*.vcxproj) reside in the appropriate - project directories. This solution file can be opened in VS 2015 + project directories. This solution file can be opened in VS 2015 or VS 2017 and should be upgraded automatically if VS 2013 is not also installed. Note: Tests have their own solution files. diff --git a/modules/expat/win32/expat.iss b/modules/expat/win32/expat.iss index add8445f..2943d3e1 100644 --- a/modules/expat/win32/expat.iss +++ b/modules/expat/win32/expat.iss @@ -7,17 +7,17 @@ [Setup] AppName=Expat AppId=expat -AppVersion=2.2.0 -AppVerName=Expat 2.2.0 -AppCopyright=Copyright © 1998-2016 Thai Open Source Software Center, Clark Cooper, and the Expat maintainers +AppVersion=2.2.1 +AppVerName=Expat 2.2.1 +AppCopyright=Copyright � 1998-2017 Thai Open Source Software Center, Clark Cooper, and the Expat maintainers AppPublisher=The Expat Developers AppPublisherURL=http://www.libexpat.org/ AppSupportURL=http://www.libexpat.org/ AppUpdatesURL=http://www.libexpat.org/ -UninstallDisplayName=Expat XML Parser 2.2.0 -VersionInfoVersion=2.2.0 +UninstallDisplayName=Expat XML Parser 2.2.1 +VersionInfoVersion=2.2.1 -DefaultDirName={pf}\Expat 2.2.0 +DefaultDirName={pf}\Expat 2.2.1 UninstallFilesDir={app}\Uninstall Compression=lzma @@ -32,6 +32,7 @@ DisableReadyPage=yes [Files] Flags: ignoreversion; Source: win32\bin\Release\xmlwf.exe; DestDir: "{app}\Bin" Flags: ignoreversion; Source: win32\MANIFEST.txt; DestDir: "{app}" +Flags: ignoreversion; Source: AUTHORS; DestDir: "{app}"; DestName: AUTHORS.txt Flags: ignoreversion; Source: Changes; DestDir: "{app}"; DestName: Changes.txt Flags: ignoreversion; Source: COPYING; DestDir: "{app}"; DestName: COPYING.txt Flags: ignoreversion; Source: README; DestDir: "{app}"; DestName: README.txt @@ -40,40 +41,29 @@ Flags: ignoreversion; Source: doc\*.css; DestDir: "{app}\Doc" Flags: ignoreversion; Source: doc\*.png; DestDir: "{app}\Doc" Flags: ignoreversion; Source: win32\bin\Release\*.dll; DestDir: "{app}\Bin" Flags: ignoreversion; Source: win32\bin\Release\*.lib; DestDir: "{app}\Bin" -Flags: ignoreversion; Source: expat.dsw; DestDir: "{app}\Source" Flags: ignoreversion; Source: expat.sln; DestDir: "{app}\Source" Flags: ignoreversion; Source: win32\README.txt; DestDir: "{app}\Source" -Flags: ignoreversion; Source: bcb5\*.bp*; DestDir: "{app}\Source\bcb5" -Flags: ignoreversion; Source: bcb5\*.mak; DestDir: "{app}\Source\bcb5" -Flags: ignoreversion; Source: bcb5\*.def; DestDir: "{app}\Source\bcb5" -Flags: ignoreversion; Source: bcb5\*.txt; DestDir: "{app}\Source\bcb5" -Flags: ignoreversion; Source: bcb5\*.bat; DestDir: "{app}\Source\bcb5" Flags: ignoreversion; Source: lib\*.c; DestDir: "{app}\Source\lib" Flags: ignoreversion; Source: lib\*.h; DestDir: "{app}\Source\lib" Flags: ignoreversion; Source: lib\*.def; DestDir: "{app}\Source\lib" -Flags: ignoreversion; Source: lib\*.dsp; DestDir: "{app}\Source\lib" Flags: ignoreversion; Source: lib\*.vcxproj; DestDir: "{app}\Source\lib" Flags: ignoreversion; Source: lib\*.vcxproj.filters; DestDir: "{app}\Source\lib" Flags: ignoreversion; Source: examples\*.c; DestDir: "{app}\Source\examples" -Flags: ignoreversion; Source: examples\*.dsp; DestDir: "{app}\Source\examples" Flags: ignoreversion; Source: examples\*.vcxproj; DestDir: "{app}\Source\examples" Flags: ignoreversion; Source: examples\*.vcxproj.filters; DestDir: "{app}\Source\examples" Flags: ignoreversion; Source: tests\*.c; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\*.cpp; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\*.h; DestDir: "{app}\Source\tests" -Flags: ignoreversion; Source: tests\*.ds*; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\*.sln; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\*.vcxproj; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\*.vcxproj.filters; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\README.txt; DestDir: "{app}\Source\tests" Flags: ignoreversion; Source: tests\benchmark\*.c; DestDir: "{app}\Source\tests\benchmark" -Flags: ignoreversion; Source: tests\benchmark\*.ds*; DestDir: "{app}\Source\tests\benchmark" Flags: ignoreversion; Source: tests\benchmark\*.sln; DestDir: "{app}\Source\tests\benchmark" Flags: ignoreversion; Source: tests\benchmark\*.vcxproj; DestDir: "{app}\Source\tests\benchmark" Flags: ignoreversion; Source: tests\benchmark\README.txt; DestDir: "{app}\Source\tests\benchmark" Flags: ignoreversion; Source: xmlwf\*.c*; DestDir: "{app}\Source\xmlwf" Flags: ignoreversion; Source: xmlwf\*.h; DestDir: "{app}\Source\xmlwf" -Flags: ignoreversion; Source: xmlwf\*.dsp; DestDir: "{app}\Source\xmlwf" Flags: ignoreversion; Source: xmlwf\*.vcxproj; DestDir: "{app}\Source\xmlwf" Flags: ignoreversion; Source: xmlwf\*.vcxproj.filters; DestDir: "{app}\Source\xmlwf" diff --git a/modules/expat/xmlwf/.gitignore b/modules/expat/xmlwf/.gitignore new file mode 100755 index 00000000..90464b41 --- /dev/null +++ b/modules/expat/xmlwf/.gitignore @@ -0,0 +1,6 @@ +Debug +Release +xmlwf.plg +Makefile +xmlwf +.libs diff --git a/modules/expat/xmlwf/codepage.c b/modules/expat/xmlwf/codepage.c index 91bd15e9..7d78f21e 100644 --- a/modules/expat/xmlwf/codepage.c +++ b/modules/expat/xmlwf/codepage.c @@ -5,7 +5,7 @@ #include "codepage.h" #include "internal.h" /* for UNUSED_P only */ -#if (defined(WIN32) || (defined(__WATCOMC__) && defined(__NT__))) +#if defined(_WIN32) #define STRICT 1 #define WIN32_LEAN_AND_MEAN 1 @@ -52,7 +52,7 @@ codepageConvert(int cp, const char *p) return -1; } -#else /* not WIN32 */ +#else /* not _WIN32 */ int codepageMap(int UNUSED_P(cp), int *UNUSED_P(map)) @@ -66,4 +66,4 @@ codepageConvert(int UNUSED_P(cp), const char *UNUSED_P(p)) return -1; } -#endif /* not WIN32 */ +#endif /* not _WIN32 */ diff --git a/modules/expat/xmlwf/filemap.h b/modules/expat/xmlwf/filemap.h index 814edec2..db83d1a0 100644 --- a/modules/expat/xmlwf/filemap.h +++ b/modules/expat/xmlwf/filemap.h @@ -2,8 +2,20 @@ See the file COPYING for copying permission. */ +#include /* INT_MAX */ #include + +/* The following limit (for XML_Parse's int len) derives from + * this loop in xmparse.c: + * + * do { + * bufferSize = (int) (2U * (unsigned) bufferSize); + * } while (bufferSize < neededSize && bufferSize > 0); + */ +#define XML_MAX_CHUNK_LEN (INT_MAX / 2 + 1) + + #ifdef XML_UNICODE int filemap(const wchar_t *name, void (*processor)(const void *, size_t, diff --git a/modules/expat/xmlwf/readfilemap.c b/modules/expat/xmlwf/readfilemap.c index d816b263..023998ef 100644 --- a/modules/expat/xmlwf/readfilemap.c +++ b/modules/expat/xmlwf/readfilemap.c @@ -9,16 +9,8 @@ #include /* Functions close(2) and read(2) */ -#ifdef __WATCOMC__ -#ifndef __LINUX__ -#include -#else -#include -#endif -#else -# if !defined(WIN32) && !defined(_WIN32) && !defined(_WIN64) -# include -# endif +#if !defined(_WIN32) && !defined(_WIN64) +# include #endif #ifndef S_ISREG @@ -67,6 +59,11 @@ filemap(const char *name, close(fd); return 0; } + if (sb.st_size > XML_MAX_CHUNK_LEN) { + close(fd); + return 2; /* Cannot be passed to XML_Parse in one go */ + } + nbytes = sb.st_size; /* malloc will return NULL with nbytes == 0, handle files with size 0 */ if (nbytes == 0) { diff --git a/modules/expat/xmlwf/unixfilemap.c b/modules/expat/xmlwf/unixfilemap.c index e13299da..8783134c 100644 --- a/modules/expat/xmlwf/unixfilemap.c +++ b/modules/expat/xmlwf/unixfilemap.c @@ -42,6 +42,10 @@ filemap(const char *name, fprintf(stderr, "%s: not a regular file\n", name); return 0; } + if (sb.st_size > XML_MAX_CHUNK_LEN) { + close(fd); + return 2; /* Cannot be passed to XML_Parse in one go */ + } nbytes = sb.st_size; /* mmap fails for zero length files */ diff --git a/modules/expat/xmlwf/win32filemap.c b/modules/expat/xmlwf/win32filemap.c index 41dc35b6..6be45962 100644 --- a/modules/expat/xmlwf/win32filemap.c +++ b/modules/expat/xmlwf/win32filemap.c @@ -42,11 +42,12 @@ filemap(const TCHAR *name, size = GetFileSize(f, &sizeHi); if (size == (DWORD)-1) { win32perror(name); + CloseHandle(f); return 0; } - if (sizeHi) { - _ftprintf(stderr, _T("%s: bigger than 2Gb\n"), name); - return 0; + if (sizeHi || (size > XML_MAX_CHUNK_LEN)) { + CloseHandle(f); + return 2; /* Cannot be passed to XML_Parse in one go */ } /* CreateFileMapping barfs on zero length files */ if (size == 0) { diff --git a/modules/expat/xmlwf/xmlfile.c b/modules/expat/xmlwf/xmlfile.c index 2f769aa8..6473c6e1 100644 --- a/modules/expat/xmlwf/xmlfile.c +++ b/modules/expat/xmlwf/xmlfile.c @@ -8,17 +8,11 @@ #include #include -#ifdef WIN32 +#ifdef _WIN32 #include "winconfig.h" -#elif defined(MACOS_CLASSIC) -#include "macconfig.h" -#elif defined(__amigaos__) -#include "amigaconfig.h" -#elif defined(__WATCOMC__) -#include "watcomconfig.h" #elif defined(HAVE_EXPAT_CONFIG_H) #include -#endif /* ndef WIN32 */ +#endif /* ndef _WIN32 */ #include "expat.h" #include "internal.h" /* for UNUSED_P only */ @@ -26,14 +20,10 @@ #include "xmltchar.h" #include "filemap.h" -#if (defined(_MSC_VER) || (defined(__WATCOMC__) && !defined(__LINUX__))) +#if defined(_MSC_VER) #include #endif -#if defined(__amigaos__) && defined(__USE_INLINE__) -#include -#endif - #ifdef HAVE_UNISTD_H #include #endif @@ -58,6 +48,9 @@ typedef struct { int *retPtr; } PROCESS_ARGS; +static int +processStream(const XML_Char *filename, XML_Parser parser); + static void reportError(XML_Parser parser, const XML_Char *filename) { @@ -88,7 +81,7 @@ processFile(const void *data, size_t size, *retPtr = 1; } -#if (defined(WIN32) || defined(__WATCOMC__)) +#if defined(_WIN32) static int isAsciiLetter(XML_Char c) @@ -96,7 +89,7 @@ isAsciiLetter(XML_Char c) return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z')); } -#endif /* WIN32 */ +#endif /* _WIN32 */ static const XML_Char * resolveSystemId(const XML_Char *base, const XML_Char *systemId, @@ -106,7 +99,7 @@ resolveSystemId(const XML_Char *base, const XML_Char *systemId, *toFree = 0; if (!base || *systemId == T('/') -#if (defined(WIN32) || defined(__WATCOMC__)) +#if defined(_WIN32) || *systemId == T('\\') || (isAsciiLetter(systemId[0]) && systemId[1] == T(':')) #endif @@ -120,7 +113,7 @@ resolveSystemId(const XML_Char *base, const XML_Char *systemId, s = *toFree; if (tcsrchr(s, T('/'))) s = tcsrchr(s, T('/')) + 1; -#if (defined(WIN32) || defined(__WATCOMC__)) +#if defined(_WIN32) if (tcsrchr(s, T('\\'))) s = tcsrchr(s, T('\\')) + 1; #endif @@ -139,13 +132,23 @@ externalEntityRefFilemap(XML_Parser parser, XML_Char *s; const XML_Char *filename; XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0); + int filemapRes; PROCESS_ARGS args; args.retPtr = &result; args.parser = entParser; filename = resolveSystemId(base, systemId, &s); XML_SetBase(entParser, filename); - if (!filemap(filename, processFile, &args)) + filemapRes = filemap(filename, processFile, &args); + switch (filemapRes) { + case 0: result = 0; + break; + case 2: + ftprintf(stderr, T("%s: file too large for memory-mapping") + T(", switching to streaming\n"), filename); + result = processStream(filename, entParser); + break; + } free(s); XML_ParserFree(entParser); return result; @@ -233,11 +236,21 @@ XML_ProcessFile(XML_Parser parser, ? externalEntityRefFilemap : externalEntityRefStream); if (flags & XML_MAP_FILE) { + int filemapRes; PROCESS_ARGS args; args.retPtr = &result; args.parser = parser; - if (!filemap(filename, processFile, &args)) + filemapRes = filemap(filename, processFile, &args); + switch (filemapRes) { + case 0: result = 0; + break; + case 2: + ftprintf(stderr, T("%s: file too large for memory-mapping") + T(", switching to streaming\n"), filename); + result = processStream(filename, parser); + break; + } } else result = processStream(filename, parser); diff --git a/modules/expat/xmlwf/xmlwf.c b/modules/expat/xmlwf/xmlwf.c index 66d6c9ef..7581c078 100644 --- a/modules/expat/xmlwf/xmlwf.c +++ b/modules/expat/xmlwf/xmlwf.c @@ -17,10 +17,6 @@ #include #endif -#if defined(__amigaos__) && defined(__USE_INLINE__) -#include -#endif - /* This ensures proper sorting. */ #define NSSEP T('\001') @@ -608,7 +604,7 @@ showVersion(XML_Char *prog) const XML_Feature *features = XML_GetFeatureList(); while ((ch = *s) != 0) { if (ch == '/' -#if (defined(WIN32) || defined(__WATCOMC__)) +#if defined(_WIN32) || ch == '\\' #endif ) @@ -785,7 +781,7 @@ tmain(int argc, XML_Char **argv) const XML_Char * lastDelim = tcsrchr(file, delim[0]); if (lastDelim) file = lastDelim + 1; -#if (defined(WIN32) || defined(__WATCOMC__)) +#if defined(_WIN32) else { const XML_Char * winDelim = T("\\"); lastDelim = tcsrchr(file, winDelim[0]); diff --git a/modules/expat/xmlwf/xmlwf.vcxproj b/modules/expat/xmlwf/xmlwf.vcxproj new file mode 100644 index 00000000..0a511c6c --- /dev/null +++ b/modules/expat/xmlwf/xmlwf.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + {E3C5991F-5238-4168-A179-275D1AC98D7E} + + + + Application + v120 + + + Application + v120 + false + + + Application + v120 + false + + + + + + + + + + + + + + + + + + .\..\win32\bin\Release\ + .\..\win32\tmp\Release-xmlwf\ + false + + + .\..\win32\bin\Debug\ + .\..\win32\tmp\Debug-xmlwf\ + true + + + + MultiThreaded + Default + true + true + MaxSpeed + true + Level3 + ..\lib;%(AdditionalIncludeDirectories) + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\..\win32\tmp\Release-xmlwf\ + .\..\win32\tmp\Release-xmlwf\xmlwf.pch + + .\..\win32\tmp\Release-xmlwf\ + .\..\win32\tmp\Release-xmlwf\ + + + .\..\win32\bin\Release\xmlwf.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Release\xmlwf.bsc + + + true + Console + false + ..\win32\bin\Release\xmlwf.exe + ..\win32\bin\Release;%(AdditionalLibraryDirectories) + libexpat.lib;setargv.obj;%(AdditionalDependencies) + + + + + MultiThreadedDebug + Default + true + Disabled + true + Level3 + EditAndContinue + ..\lib;%(AdditionalIncludeDirectories) + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + .\..\win32\tmp\Debug-xmlwf\ + .\..\win32\tmp\Debug-xmlwf\xmlwf.pch + .\..\win32\tmp\Debug-xmlwf\ + .\..\win32\tmp\Debug-xmlwf\ + + + .\..\win32\bin\Debug\xmlwf.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\..\win32\bin\Debug\xmlwf.bsc + + + true + true + Console + ..\win32\bin\Debug\xmlwf.exe + ..\win32\bin\Debug;%(AdditionalLibraryDirectories) + libexpat.lib;setargv.obj;%(AdditionalDependencies) + + + + + + true + true + + + true + true + + + + + + + + + + + + + {45a5074d-66e8-44a4-a03f-018027b528d6} + false + + + + + + \ No newline at end of file diff --git a/modules/expat/xmlwf/xmlwf.vcxproj.filters b/modules/expat/xmlwf/xmlwf.vcxproj.filters new file mode 100644 index 00000000..890b9efb --- /dev/null +++ b/modules/expat/xmlwf/xmlwf.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {843deb01-ec59-4070-9fb7-4de851940fbd} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90 + + + {41225059-d26f-42fd-9d1b-fda760b7e45d} + h;hpp;hxx;hm;inl;fi;fd + + + {a722469e-558e-4d77-b8ea-88c9f136e29a} + ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file