mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-09 21:14:02 +00:00
add xmlrpc-c 1.03.14 to in tree libs
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3772 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/..
|
||||
endif
|
||||
SUBDIR = lib
|
||||
|
||||
include $(SRCDIR)/Makefile.config
|
||||
|
||||
SUBDIRS = util
|
||||
ifeq ($(ENABLE_ABYSS_SERVER),yes)
|
||||
SUBDIRS += abyss
|
||||
endif
|
||||
ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
|
||||
SUBDIRS += wininet_transport
|
||||
endif
|
||||
ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
|
||||
SUBDIRS += curl_transport
|
||||
endif
|
||||
ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
|
||||
SUBDIRS += libwww_transport
|
||||
endif
|
||||
ifneq ($(ENABLE_LIBXML2),yes)
|
||||
SUBDIRS += expat
|
||||
endif
|
||||
|
||||
default: all
|
||||
|
||||
.PHONY: all
|
||||
all: $(SUBDIRS:%=%/all)
|
||||
|
||||
.PHONY: clean
|
||||
clean: $(SUBDIRS:%=%/clean) clean-common
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: $(SUBDIRS:%=%/distclean) distclean-common
|
||||
|
||||
.PHONY: tags
|
||||
tags: $(SUBDIRS:%=%/tags) TAGS
|
||||
|
||||
DISTFILES =
|
||||
|
||||
.PHONY: distdir
|
||||
distdir: distdir-common
|
||||
|
||||
.PHONY: install
|
||||
install: $(SUBDIRS:%=%/install)
|
||||
|
||||
.PHONY: dep
|
||||
dep: $(SUBDIRS:%=%/dep)
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../..
|
||||
endif
|
||||
SUBDIR = lib/abyss
|
||||
|
||||
include $(SRCDIR)/Makefile.config
|
||||
|
||||
SUBDIRS = src
|
||||
|
||||
default: all
|
||||
|
||||
.PHONY: all
|
||||
all: $(SUBDIRS:%=%/all)
|
||||
|
||||
.PHONY: clean
|
||||
clean: $(SUBDIRS:%=%/clean) clean-common
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: $(SUBDIRS:%=%/distclean) distclean-common
|
||||
|
||||
.PHONY: tags
|
||||
tags: $(SUBDIRS:%=%/tags) TAGS
|
||||
|
||||
DISTFILES =
|
||||
|
||||
.PHONY: distdir
|
||||
distdir: distdir-common
|
||||
|
||||
.PHONY: install
|
||||
install: $(SUBDIRS:%=%/install)
|
||||
|
||||
.PHONY: dep
|
||||
dep: $(SUBDIRS:%=%/dep)
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
This directory contains the Abyss HTTP server component of XML-RPC For C/C++
|
||||
(Xmlrpc-c).
|
||||
|
||||
This was derived from the independently developed and distributed
|
||||
Abyss web server package in 2001. Since that time, work has stopped
|
||||
on package except for a non-free derivative of it that the original
|
||||
author has done. He uses the Abyss name for that.
|
||||
|
||||
So this is now strictly a piece of Xmlrpc-c. Some day, we should change
|
||||
the name to avoid confusion with the old code on which it was based and
|
||||
the current non-free version.
|
||||
|
||||
But for Xmlrpc-c, we don't want to enhance this much. That would
|
||||
duplicate the vast amount of work that has gone into other HTTP (web)
|
||||
servers such as Apache. If someone needs fancy HTTP service for
|
||||
XML-RPC, he should use Apache. One can use Apache with Xmlrpc-c
|
||||
either by using an Apache request handler plugin or by using a CGI
|
||||
script. Abyss is just for very simple servers, where the complexity
|
||||
of using (or even acquiring) Apache would not be warranted.
|
||||
|
||||
|
||||
Everything besides what's in the src/ directory is just historical --
|
||||
it comes from the original Abyss in 2001.
|
||||
@@ -0,0 +1,34 @@
|
||||
Change log for the ABYSS Web Server
|
||||
-----------------------------------
|
||||
|
||||
Version 0.3 (March 23,2000):
|
||||
----------------------------
|
||||
* Handles conditional GET requests (by date)
|
||||
* Conforms to all the MUSTs of the RFC2616 (newer version of the HTTP/1.1 protocol draft)
|
||||
* New configuration options (such as pidfile for UNIX systems...)
|
||||
* Handles HEAD and OPTIONS methods
|
||||
* Many bug fixes
|
||||
* Tested on Sun-OS 5.7
|
||||
* Second public release
|
||||
|
||||
Version 0.2 beta (February 7,2000):
|
||||
-----------------------------------
|
||||
* Handles GET on static files
|
||||
* Handles correctly range requests
|
||||
* Conforms to 80% of the MUSTs of the RFC2068 (HTTP/1.1 protocol draft)
|
||||
* Improved code portability (Win32 and UNIX platforms)
|
||||
* Tested on Linux 2.2 and Win95/98
|
||||
* First public release
|
||||
|
||||
Version 0.1 (January 2000):
|
||||
---------------------------
|
||||
* Completely rewritten in C
|
||||
* Speed improvement
|
||||
* New memory allocation scheme (using pools)
|
||||
* Never released
|
||||
|
||||
Version 0.0 (January 2000):
|
||||
---------------------------
|
||||
* Initial version
|
||||
* Written in C++
|
||||
* Never released
|
||||
@@ -0,0 +1,56 @@
|
||||
# ABYSS Web Server configuration file
|
||||
# (C) Moez Mahfoudh - 2000
|
||||
|
||||
# Cases in option names are ignored,
|
||||
# that means that PORT=port=PoRT=..
|
||||
|
||||
# When writing paths, do not worry about / or \ use.
|
||||
# ABYSS will substitute / with \ on Win32 systems.
|
||||
|
||||
# Options which are system specific (such as User) are
|
||||
# ignored on systems which do not handle them.
|
||||
|
||||
# The Port option tells the server on which TCP port to listen.
|
||||
# default is 80
|
||||
Port 8000
|
||||
|
||||
# The name or #number of the user to run the server as if it is
|
||||
# launched as root (UNIX specific)
|
||||
User nobody
|
||||
|
||||
# The Server Root (UNIX systems style)
|
||||
ServerRoot /home/mahfoudh/abyss
|
||||
|
||||
# The Server Root (Win32 systems style)
|
||||
# ServerRoot c:\abyss
|
||||
|
||||
# The Path option specifies the web files path.
|
||||
Path htdocs
|
||||
|
||||
# The Default option contains the name of the files the server should
|
||||
# look for when only a path is given (e.g. http://myserver/info/).
|
||||
Default index.html index.htm INDEX.HTM INDEX.HTML
|
||||
|
||||
# The KeepAlive option is used to set the maximum number of requests
|
||||
# served using the same persistent connection.
|
||||
KeepAlive 10
|
||||
|
||||
# The TimeOut option tells the server how much seconds to wait for
|
||||
# an idle connection before closing it.
|
||||
TimeOut 10
|
||||
|
||||
# The MimeTypes option specifies the location of the file
|
||||
# containing the mapping of MIME types and files extensions
|
||||
MimeTypes conf/mime.types
|
||||
|
||||
# The path of the log file
|
||||
LogFile log/access.log
|
||||
|
||||
# The file where the pid of the server is logged (UNIX specific)
|
||||
PidFile log/abyss.pid
|
||||
|
||||
# If AdvertiseServer if set to no, then no server field would be
|
||||
# appended to the responses. This is the way to make the server
|
||||
# identity unknown to some malicious people which can profit from
|
||||
# well known security holes in the software to crash it.
|
||||
AdvertiseServer yes
|
||||
@@ -0,0 +1,276 @@
|
||||
# This is a comment. I love comments.
|
||||
|
||||
# This file controls what Internet media types are sent to the client for
|
||||
# given file extension(s). Sending the correct media type to the client
|
||||
# is important so they know how to handle the content of the file.
|
||||
# Extra types can either be added here or by using an AddType directive
|
||||
# in your config files. For more information about Internet media types,
|
||||
# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type
|
||||
# registry is at <ftp://ftp.iana.org/in-notes/iana/assignments/media-types/>.
|
||||
|
||||
# MIME type Extension
|
||||
application/EDI-Consent
|
||||
application/EDI-X12
|
||||
application/EDIFACT
|
||||
application/activemessage
|
||||
application/andrew-inset ez
|
||||
application/applefile
|
||||
application/atomicmail
|
||||
application/cals-1840
|
||||
application/commonground
|
||||
application/cybercash
|
||||
application/dca-rft
|
||||
application/dec-dx
|
||||
application/eshop
|
||||
application/hyperstudio
|
||||
application/iges
|
||||
application/mac-binhex40 hqx
|
||||
application/mac-compactpro cpt
|
||||
application/macwriteii
|
||||
application/marc
|
||||
application/mathematica
|
||||
application/msword doc
|
||||
application/news-message-id
|
||||
application/news-transmission
|
||||
application/octet-stream bin dms lha lzh exe class
|
||||
application/oda oda
|
||||
application/pdf pdf
|
||||
application/pgp-encrypted
|
||||
application/pgp-keys
|
||||
application/pgp-signature
|
||||
application/pkcs10
|
||||
application/pkcs7-mime
|
||||
application/pkcs7-signature
|
||||
application/postscript ai eps ps
|
||||
application/prs.alvestrand.titrax-sheet
|
||||
application/prs.cww
|
||||
application/prs.nprend
|
||||
application/remote-printing
|
||||
application/riscos
|
||||
application/rtf rtf
|
||||
application/set-payment
|
||||
application/set-payment-initiation
|
||||
application/set-registration
|
||||
application/set-registration-initiation
|
||||
application/sgml
|
||||
application/sgml-open-catalog
|
||||
application/slate
|
||||
application/smil smi smil
|
||||
application/vemmi
|
||||
application/vnd.3M.Post-it-Notes
|
||||
application/vnd.FloGraphIt
|
||||
application/vnd.acucobol
|
||||
application/vnd.anser-web-certificate-issue-initiation
|
||||
application/vnd.anser-web-funds-transfer-initiation
|
||||
application/vnd.audiograph
|
||||
application/vnd.businessobjects
|
||||
application/vnd.claymore
|
||||
application/vnd.comsocaller
|
||||
application/vnd.dna
|
||||
application/vnd.dxr
|
||||
application/vnd.ecdis-update
|
||||
application/vnd.ecowin.chart
|
||||
application/vnd.ecowin.filerequest
|
||||
application/vnd.ecowin.fileupdate
|
||||
application/vnd.ecowin.series
|
||||
application/vnd.ecowin.seriesrequest
|
||||
application/vnd.ecowin.seriesupdate
|
||||
application/vnd.enliven
|
||||
application/vnd.epson.salt
|
||||
application/vnd.fdf
|
||||
application/vnd.ffsns
|
||||
application/vnd.framemaker
|
||||
application/vnd.fujitsu.oasys
|
||||
application/vnd.fujitsu.oasys2
|
||||
application/vnd.fujitsu.oasys3
|
||||
application/vnd.fujitsu.oasysgp
|
||||
application/vnd.fujitsu.oasysprs
|
||||
application/vnd.fujixerox.docuworks
|
||||
application/vnd.hp-HPGL
|
||||
application/vnd.hp-PCL
|
||||
application/vnd.hp-PCLXL
|
||||
application/vnd.hp-hps
|
||||
application/vnd.ibm.MiniPay
|
||||
application/vnd.ibm.modcap
|
||||
application/vnd.intercon.formnet
|
||||
application/vnd.intertrust.digibox
|
||||
application/vnd.intertrust.nncp
|
||||
application/vnd.is-xpr
|
||||
application/vnd.japannet-directory-service
|
||||
application/vnd.japannet-jpnstore-wakeup
|
||||
application/vnd.japannet-payment-wakeup
|
||||
application/vnd.japannet-registration
|
||||
application/vnd.japannet-registration-wakeup
|
||||
application/vnd.japannet-setstore-wakeup
|
||||
application/vnd.japannet-verification
|
||||
application/vnd.japannet-verification-wakeup
|
||||
application/vnd.koan
|
||||
application/vnd.lotus-1-2-3
|
||||
application/vnd.lotus-approach
|
||||
application/vnd.lotus-freelance
|
||||
application/vnd.lotus-organizer
|
||||
application/vnd.lotus-screencam
|
||||
application/vnd.lotus-wordpro
|
||||
application/vnd.meridian-slingshot
|
||||
application/vnd.mif mif
|
||||
application/vnd.minisoft-hp3000-save
|
||||
application/vnd.mitsubishi.misty-guard.trustweb
|
||||
application/vnd.ms-artgalry
|
||||
application/vnd.ms-asf
|
||||
application/vnd.ms-excel xls
|
||||
application/vnd.ms-powerpoint ppt
|
||||
application/vnd.ms-project
|
||||
application/vnd.ms-tnef
|
||||
application/vnd.ms-works
|
||||
application/vnd.music-niff
|
||||
application/vnd.musician
|
||||
application/vnd.netfpx
|
||||
application/vnd.noblenet-directory
|
||||
application/vnd.noblenet-sealer
|
||||
application/vnd.noblenet-web
|
||||
application/vnd.novadigm.EDM
|
||||
application/vnd.novadigm.EDX
|
||||
application/vnd.novadigm.EXT
|
||||
application/vnd.osa.netdeploy
|
||||
application/vnd.powerbuilder6
|
||||
application/vnd.powerbuilder6-s
|
||||
application/vnd.rapid
|
||||
application/vnd.seemail
|
||||
application/vnd.shana.informed.formtemplate
|
||||
application/vnd.shana.informed.interchange
|
||||
application/vnd.shana.informed.package
|
||||
application/vnd.street-stream
|
||||
application/vnd.svd
|
||||
application/vnd.swiftview-ics
|
||||
application/vnd.truedoc
|
||||
application/vnd.visio
|
||||
application/vnd.webturbo
|
||||
application/vnd.wrq-hp3000-labelled
|
||||
application/vnd.wt.stf
|
||||
application/vnd.xara
|
||||
application/vnd.yellowriver-custom-menu
|
||||
application/wita
|
||||
application/wordperfect5.1
|
||||
application/x-bcpio bcpio
|
||||
application/x-cdlink vcd
|
||||
application/x-chess-pgn pgn
|
||||
application/x-compress
|
||||
application/x-cpio cpio
|
||||
application/x-csh csh
|
||||
application/x-director dcr dir dxr
|
||||
application/x-dvi dvi
|
||||
application/x-futuresplash spl
|
||||
application/x-gtar gtar
|
||||
application/x-gzip
|
||||
application/x-hdf hdf
|
||||
application/x-javascript js
|
||||
application/x-koan skp skd skt skm
|
||||
application/x-latex latex
|
||||
application/x-netcdf nc cdf
|
||||
application/x-sh sh
|
||||
application/x-shar shar
|
||||
application/x-shockwave-flash swf
|
||||
application/x-stuffit sit
|
||||
application/x-sv4cpio sv4cpio
|
||||
application/x-sv4crc sv4crc
|
||||
application/x-tar tar
|
||||
application/x-tcl tcl
|
||||
application/x-tex tex
|
||||
application/x-texinfo texinfo texi
|
||||
application/x-troff t tr roff
|
||||
application/x-troff-man man
|
||||
application/x-troff-me me
|
||||
application/x-troff-ms ms
|
||||
application/x-ustar ustar
|
||||
application/x-wais-source src
|
||||
application/x400-bp
|
||||
application/xml
|
||||
application/zip zip
|
||||
audio/32kadpcm
|
||||
audio/basic au snd
|
||||
audio/midi mid midi kar
|
||||
audio/mpeg mpga mp2 mp3
|
||||
audio/vnd.qcelp
|
||||
audio/x-aiff aif aiff aifc
|
||||
audio/x-pn-realaudio ram rm
|
||||
audio/x-pn-realaudio-plugin rpm
|
||||
audio/x-realaudio ra
|
||||
audio/x-wav wav
|
||||
chemical/x-pdb pdb xyz
|
||||
image/bmp bmp
|
||||
image/cgm
|
||||
image/g3fax
|
||||
image/gif gif
|
||||
image/ief ief
|
||||
image/jpeg jpeg jpg jpe
|
||||
image/naplps
|
||||
image/png png
|
||||
image/prs.btif
|
||||
image/tiff tiff tif
|
||||
image/vnd.dwg
|
||||
image/vnd.dxf
|
||||
image/vnd.fpx
|
||||
image/vnd.net-fpx
|
||||
image/vnd.svf
|
||||
image/vnd.xiff
|
||||
image/x-cmu-raster ras
|
||||
image/x-portable-anymap pnm
|
||||
image/x-portable-bitmap pbm
|
||||
image/x-portable-graymap pgm
|
||||
image/x-portable-pixmap ppm
|
||||
image/x-rgb rgb
|
||||
image/x-xbitmap xbm
|
||||
image/x-xpixmap xpm
|
||||
image/x-xwindowdump xwd
|
||||
message/delivery-status
|
||||
message/disposition-notification
|
||||
message/external-body
|
||||
message/http
|
||||
message/news
|
||||
message/partial
|
||||
message/rfc822
|
||||
model/iges igs iges
|
||||
model/mesh msh mesh silo
|
||||
model/vnd.dwf
|
||||
model/vrml wrl vrml
|
||||
multipart/alternative
|
||||
multipart/appledouble
|
||||
multipart/byteranges
|
||||
multipart/digest
|
||||
multipart/encrypted
|
||||
multipart/form-data
|
||||
multipart/header-set
|
||||
multipart/mixed
|
||||
multipart/parallel
|
||||
multipart/related
|
||||
multipart/report
|
||||
multipart/signed
|
||||
multipart/voice-message
|
||||
text/css css
|
||||
text/directory
|
||||
text/enriched
|
||||
text/html html htm
|
||||
text/plain asc txt
|
||||
text/prs.lines.tag
|
||||
text/rfc822-headers
|
||||
text/richtext rtx
|
||||
text/rtf rtf
|
||||
text/sgml sgml sgm
|
||||
text/tab-separated-values tsv
|
||||
text/uri-list
|
||||
text/vnd.abc
|
||||
text/vnd.flatland.3dml
|
||||
text/vnd.fmi.flexstor
|
||||
text/vnd.in3d.3dml
|
||||
text/vnd.in3d.spot
|
||||
text/vnd.latex-z
|
||||
text/x-setext etx
|
||||
text/xml xml
|
||||
video/mpeg mpeg mpg mpe
|
||||
video/quicktime qt mov
|
||||
video/vnd.motorola.video
|
||||
video/vnd.motorola.videop
|
||||
video/vnd.vivo
|
||||
video/x-msvideo avi
|
||||
video/x-sgi-movie movie
|
||||
x-conference/x-cooltalk ice
|
||||
@@ -0,0 +1,21 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>ABYSS is working !!!</TITLE>
|
||||
</HEAD>
|
||||
<BODY bgColor=#80a0f0 text=#000000>
|
||||
<H1 align=center>Congratulations, ABYSS is working !!!</H1>
|
||||
<BR>
|
||||
<P>
|
||||
<B>ABYSS</B> Web Server is working correctly on your system. You should now change this
|
||||
page with yours.
|
||||
<BR>
|
||||
Please include in your web pages (at least the first), the <b><i>'Powered by ABYSS'</i></b>
|
||||
banner to promote the use of <B>ABYSS</B>.
|
||||
</P>
|
||||
<hr>
|
||||
<P>
|
||||
<CENTER><FONT size=-1>
|
||||
Copyright © 2000 <A href="mailto:mmoez@bigfoot.com">Moez Mahfoudh</A>. All rights reserved.
|
||||
</FONT>
|
||||
<BR><BR><A href="http://abyss.linuxave.net/"><IMG border=0 src="pwrabyss.gif"></A></center></P>
|
||||
</BODY></HTML>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,27 @@
|
||||
ABYSS Web Server License
|
||||
------------------------
|
||||
|
||||
Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
@@ -0,0 +1,114 @@
|
||||
Notes about the Abyss Patch -- By: Rosimildo da Silva, Jan 31, 2001.
|
||||
-------------------------------------------------------------------
|
||||
|
||||
This file contains some notes about the changes made to the
|
||||
Abyss source tree. The changes were required to fix a few
|
||||
bugs, and port the base code to compile under CygWin,
|
||||
and Borland C++ free compiler. The free compiler for
|
||||
Win32 from Borland can be downloaded from here:
|
||||
|
||||
http://www.borland.com/bcppbuilder/freecompiler/
|
||||
|
||||
|
||||
What is new:
|
||||
|
||||
+ Package should compile out of the box under CygWin
|
||||
|
||||
+ Added makefiles and changes to use Borland C++ compiler
|
||||
under WIN32 as well as VC++ 6.0
|
||||
|
||||
+ Fix Abyss.dsp to use the proper thread safe libraries,
|
||||
and updated to VC++ 6.0
|
||||
|
||||
+ Fixed thread leaks ( handles )
|
||||
|
||||
|
||||
|
||||
Applying the patch to Abyss-0.3.tar.gz
|
||||
--------------------------------------
|
||||
|
||||
+ get archive from here:
|
||||
http://abyss.linuxave.net/abyss-0.3.tar.gz
|
||||
WARNING: this site seems to be dead for the last two months.
|
||||
|
||||
+ cd /work ( any dir )
|
||||
tar xzvf abyss-0.3.tar.gz
|
||||
cd abyss
|
||||
patch -p1 <abyss-0.3-20010131.patch
|
||||
|
||||
|
||||
What to do next:
|
||||
|
||||
|
||||
a) Cygwin
|
||||
|
||||
cd abyss/src
|
||||
make
|
||||
|
||||
|
||||
b) Borland C++
|
||||
|
||||
cd abyss\src
|
||||
set BCC_PATH=<location where your compiler is located>
|
||||
( BCC_PATH=d:\bcb5 )
|
||||
|
||||
make -f makefile.bcc32
|
||||
|
||||
c) VC++ 6.0
|
||||
cd abyss\src
|
||||
msdev Abyss.dsp
|
||||
( Or just open the workspace with Visual Studio, and you know
|
||||
the drill ).
|
||||
NOTE: Under Cygwin, after I apply the patch, Visual Studio was unable to
|
||||
recognize the workspace. ???
|
||||
|
||||
|
||||
List of changes done to the ABYSS http server: ( ChangesLog )
|
||||
----------------------------------------------
|
||||
|
||||
+ changed _WIN32 to ABYSS_WIN32. THis solve the problem that the
|
||||
macro _WIN32 is defined under CygWin. CygWin has a unix like
|
||||
api ( _UNIX ), so the macro _UNIX should be defined then.
|
||||
Under CygWin we would have _UNIX and _WIN32 defined at the same
|
||||
time.
|
||||
|
||||
|
||||
+ Theead API -- Added two extra functions: ThreadExit() and
|
||||
ThreadClose(). These allows the resources of the threads to be
|
||||
released when the thread has complete its duty serving the
|
||||
request.
|
||||
|
||||
+ Added extra flag to TConn structure to make possible the
|
||||
management of the worker threads by the server.
|
||||
|
||||
|
||||
+ Changed allocation of TConn array from stack to heap. This
|
||||
would cause problems on certain system ( specially embedded systems ),
|
||||
where the stack sizes arr not that large.
|
||||
|
||||
+ Changed ServerRun to free thread resources when the connection
|
||||
for the thread is closed.
|
||||
|
||||
+ Changed main.c to make the sginal registration conforming with
|
||||
the usage of the _FORK option.
|
||||
|
||||
+ Change ThreadCreate to be able to specify the "stack size" of the
|
||||
worker's threads ( pthread ). Defined lable for it.
|
||||
|
||||
|
||||
+ Added flag _NO_USERS to disable check for users and groups.
|
||||
This is useful for embedded systems where no users are available.
|
||||
|
||||
+ Updated VC++ workspace to version 6.0
|
||||
|
||||
|
||||
+ Changed the creation of the thread under WIN32 to use a RTL
|
||||
function ( _beginthreadex ), as recommend by MS, instead of using
|
||||
the naked WIN32 API.
|
||||
|
||||
--
|
||||
Rosimildo da Silva rdasilva@connectel.com
|
||||
ConnectTel, Inc. Austin, TX -- USA
|
||||
Phone : 512-338-1111 Fax : 512-918-0449
|
||||
Company Page: http://www.connecttel.com
|
||||
Home Page: http://members.nbci.com/rosimildo/
|
||||
@@ -0,0 +1,160 @@
|
||||
|
||||
|
||||
ABYSS Web Server
|
||||
------------------
|
||||
|
||||
|
||||
About:
|
||||
------
|
||||
|
||||
ABYSS aims to be a fully HTTP/1.1 compliant web server. Its main design
|
||||
goals are speed, low resource usage and portability. ABYSS works on most
|
||||
UNIX based systems and on Win32 systems (Win95/98/2000/NT).
|
||||
|
||||
Copyright:
|
||||
----------
|
||||
|
||||
Copyright (C) 2000 Moez Mahfoudh. All rights reserved.
|
||||
|
||||
Status:
|
||||
-------
|
||||
|
||||
ABYSS is still in development stage. Actual version is 0.3. Many features
|
||||
are not implemented yet but the server core works well and seems to be
|
||||
stable. It is fully reliable for serving static files on medium load sites.
|
||||
In fact, primary benchmarks show that ABYSS is 70% as fast as Apache when
|
||||
using the fork system. This rate jumps to 130% when using threads.
|
||||
On UNIX platforms, some problems occurred because of the use of the Pthreads
|
||||
library. This will be corrected in the future versions. That's why only the
|
||||
fork system is usable under UNIX. This lowers performances but guarantees
|
||||
stability.
|
||||
CGI/1.1 support is still absent from the current version but will be
|
||||
included in the near future.
|
||||
|
||||
Change Log:
|
||||
-----------
|
||||
|
||||
* Version 0.3 (March 23,2000):
|
||||
o Handles conditional GET requests (by date)
|
||||
o Conforms to all the MUSTs of the RFC2616 (newer version of the
|
||||
HTTP/1.1 protocol draft)
|
||||
o New configuration options (such as pidfile for UNIX systems...)
|
||||
o Handles HEAD and OPTIONS methods
|
||||
o Many bug fixes
|
||||
o Tested on Sun-OS 5.7
|
||||
o Second public release
|
||||
|
||||
* Version 0.2 beta (February 7,2000):
|
||||
o Handles GET on static files
|
||||
o Handles correctly range requests
|
||||
o Conforms to 80% of the MUSTs of the RFC2068 (HTTP/1.1 protocol
|
||||
draft)
|
||||
o Improved code portability (Win32 and UNIX platforms)
|
||||
o Tested on Linux 2.2 and Win95/98
|
||||
o First public release
|
||||
|
||||
* Version 0.1 (January 2000):
|
||||
o Completely rewritten in C
|
||||
o Speed improvement
|
||||
o New memory allocation scheme (using pools)
|
||||
o Never released
|
||||
|
||||
* Version 0.0 (January 2000):
|
||||
o Initial version
|
||||
o Written in C++
|
||||
o Never released
|
||||
|
||||
Downloading:
|
||||
------------
|
||||
|
||||
* Version 0.3 (current version):
|
||||
o UNIX package (source) abyss-0.3.tar.gz.
|
||||
o Win32 package is not available but you can extract source files
|
||||
from the UNIX package and compile them on Windows without any
|
||||
modification. (Sorry for this inconvenience: I have no Windows
|
||||
machine now to compile the program and to test it. If someone can
|
||||
do that, please email me the zipped package and I'll add it here).
|
||||
|
||||
* Version 0.2 beta:
|
||||
o UNIX package (source) abyss-0.2b.tar.gz.
|
||||
o Win32 package (source+binary) abyss-0.2b.zip.
|
||||
|
||||
Installation:
|
||||
-------------
|
||||
|
||||
* For UNIX systems:
|
||||
o Untar/Ungzip the distribution package with a command like tar xvfz
|
||||
abyss-x.y.tar.gz
|
||||
o Edit the Makefile src/Makefile to meet your system requirements.
|
||||
o Go to directory src and execute make.
|
||||
o The server binary is generated and stored in the bin directory.
|
||||
o Edit the conf/abyss.conf to reflect your system configuration (At
|
||||
least change the paths).
|
||||
o Goto to the bin directory and start the server by typing ./abyss
|
||||
-c ../conf/abyss.conf
|
||||
|
||||
* For Win32 systems:
|
||||
o Unzip the distribution package.
|
||||
o An executable file is already present in the bin directory.
|
||||
o If you wish to recompile the server, open the src/abyss.dsw file
|
||||
with Microsoft Visual C++ 5.0 or higher and rebuild the project.
|
||||
o Edit the conf/abyss.conf to reflect your system configuration (At
|
||||
least change the paths).
|
||||
o Goto to the bin directory and start the server by typing ./abyss
|
||||
-c ../conf/abyss.conf
|
||||
|
||||
Configuration:
|
||||
--------------
|
||||
|
||||
Edit the conf/abyss.conf file and change the values of the available
|
||||
options.
|
||||
|
||||
Bugs:
|
||||
-----
|
||||
|
||||
Please email bug reports to mmoez@bigfoot.com
|
||||
|
||||
To do:
|
||||
------
|
||||
|
||||
* CGI/1.1 support
|
||||
* Web based configuration/administration
|
||||
* Speed improvement
|
||||
* File caching system
|
||||
* Throttling
|
||||
* PUT method handling
|
||||
* ...
|
||||
|
||||
License:
|
||||
--------
|
||||
|
||||
ABYSS Web Server is licensed under a modified BSD type license:
|
||||
|
||||
Copyright (C) 2000 Moez Mahfoudh. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
* The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,136 @@
|
||||
# Microsoft Developer Studio Project File - Name="Abyss" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Abyss - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Abyss.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Abyss.mak" CFG="Abyss - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Abyss - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Abyss - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Abyss - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "../bin"
|
||||
# PROP Intermediate_Dir "objs"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib wsock32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "Abyss - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "../bin"
|
||||
# PROP Intermediate_Dir "objs"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /Gm /GX /ZI /Od /I "../../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ABYSS_WIN32" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x40c /d "_DEBUG"
|
||||
# ADD RSC /l 0x40c /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Abyss - Win32 Release"
|
||||
# Name "Abyss - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "c"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\conf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\conn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\data.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\file.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\http.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\main.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\server.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\socket.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\thread.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\trace.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\abyss.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Abyss"=.\Abyss.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../../..
|
||||
endif
|
||||
SUBDIR = lib/abyss/src
|
||||
|
||||
include $(SRCDIR)/Makefile.config
|
||||
|
||||
CFLAGS = $(CFLAGS_COMMON)
|
||||
CFLAGS += -D_UNIX
|
||||
ifeq ($(ENABLE_ABYSS_THREADS),yes)
|
||||
CFLAGS += -D_THREAD
|
||||
endif
|
||||
CFLAGS +=
|
||||
CFLAGS += $(CFLAGS_PERSONAL) $(CADD)
|
||||
LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR)
|
||||
ifeq ($(ENABLE_ABYSS_THREADS),yes)
|
||||
LIBLDFLAGS += -lpthread
|
||||
endif
|
||||
LIBLDFLAGS += $(LADD)
|
||||
|
||||
INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include
|
||||
|
||||
LTLIBRARIES_TO_INSTALL = libxmlrpc_abyss.la
|
||||
|
||||
default: all
|
||||
|
||||
.PHONY: all
|
||||
all: libxmlrpc_abyss.la
|
||||
|
||||
|
||||
ABYSS_OBJS = \
|
||||
conf.lo \
|
||||
data.lo \
|
||||
token.lo \
|
||||
trace.lo \
|
||||
file.lo \
|
||||
thread.lo \
|
||||
http.lo \
|
||||
socket.lo \
|
||||
server.lo \
|
||||
conn.lo \
|
||||
|
||||
|
||||
libxmlrpc_abyss.la: $(ABYSS_OBJS)
|
||||
$(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
|
||||
|
||||
$(ABYSS_OBJS):%.lo:%.c
|
||||
$(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) \
|
||||
$(CFLAGS) $<
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-common
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean distclean-common
|
||||
|
||||
.PHONY: tags
|
||||
tags: TAGS
|
||||
|
||||
.PHONY: distdir
|
||||
distdir:
|
||||
|
||||
.PHONY: install
|
||||
install: install-common
|
||||
|
||||
.PHONY: dep
|
||||
dep: dep-common
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
include Makefile.depend
|
||||
@@ -0,0 +1,342 @@
|
||||
/******************************************************************************
|
||||
**
|
||||
** conf.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(ABYSS_WIN32) && !defined(__BORLANDC__)
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#ifdef _UNIX
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
/*********************************************************************
|
||||
** Configuration Files Parsing Functions
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
|
||||
static abyss_bool
|
||||
ConfReadLine(TFile *f,char *buffer,uint32_t len) {
|
||||
abyss_bool r=TRUE;
|
||||
char c,*p,*z=buffer;
|
||||
|
||||
while ((--len)>0)
|
||||
{
|
||||
if (FileRead(f,buffer,1)<1)
|
||||
{
|
||||
if (z==buffer)
|
||||
r=FALSE;
|
||||
break;
|
||||
};
|
||||
|
||||
if ((*buffer==CR) || (*buffer==LF) )
|
||||
break;
|
||||
|
||||
buffer++;
|
||||
};
|
||||
|
||||
if (len==0)
|
||||
while (FileRead(f,&c,1)==1)
|
||||
if ((c==CR) || (c==LF))
|
||||
break;
|
||||
|
||||
*buffer='\0';
|
||||
|
||||
/* Discard comments */
|
||||
p=strchr(z,'#');
|
||||
if (p)
|
||||
*p='\0';
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static abyss_bool
|
||||
ConfNextToken(char **p) {
|
||||
while (1)
|
||||
switch (**p)
|
||||
{
|
||||
case '\t':
|
||||
case ' ':
|
||||
(*p)++;
|
||||
break;
|
||||
case '\0':
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
};
|
||||
}
|
||||
|
||||
static char *
|
||||
ConfGetToken(char **p) {
|
||||
char *p0=*p;
|
||||
|
||||
while (1)
|
||||
switch (**p)
|
||||
{
|
||||
case '\t':
|
||||
case ' ':
|
||||
case CR:
|
||||
case LF:
|
||||
case '\0':
|
||||
if (p0==*p)
|
||||
return NULL;
|
||||
|
||||
if (**p)
|
||||
{
|
||||
**p='\0';
|
||||
(*p)++;
|
||||
};
|
||||
return p0;
|
||||
|
||||
default:
|
||||
(*p)++;
|
||||
};
|
||||
}
|
||||
|
||||
static abyss_bool
|
||||
ConfReadInt(char *p,int32_t *n,int32_t min,int32_t max) {
|
||||
char *e;
|
||||
|
||||
*n=strtol(p,&e,10);
|
||||
|
||||
if (min!=max)
|
||||
return ((e!=p) && (*n>=min) && (*n<=max));
|
||||
else
|
||||
return (e!=p);
|
||||
}
|
||||
|
||||
static abyss_bool
|
||||
ConfReadBool(char *p, abyss_bool *b) {
|
||||
if (strcasecmp(p,"yes")==0)
|
||||
{
|
||||
*b=TRUE;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
if (strcasecmp(p,"no")==0)
|
||||
{
|
||||
*b=FALSE;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
** MIME Types File
|
||||
*********************************************************************/
|
||||
|
||||
abyss_bool ConfReadMIMETypes(char *filename)
|
||||
{
|
||||
TFile f;
|
||||
char z[512],*p;
|
||||
char *mimetype,*ext;
|
||||
|
||||
if (!FileOpen(&f,filename,O_RDONLY))
|
||||
return FALSE;
|
||||
|
||||
while (ConfReadLine(&f,z,512))
|
||||
{
|
||||
p=z;
|
||||
|
||||
if (ConfNextToken(&p)) {
|
||||
mimetype=ConfGetToken(&p);
|
||||
if (mimetype) {
|
||||
while (ConfNextToken(&p)) {
|
||||
ext=ConfGetToken(&p);
|
||||
if (ext)
|
||||
MIMETypeAdd(mimetype,ext);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
FileClose(&f);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
** Server Configuration File
|
||||
*********************************************************************/
|
||||
|
||||
abyss_bool ConfReadServerFile(const char *filename,TServer *srv)
|
||||
{
|
||||
TFile f;
|
||||
char z[512],*p;
|
||||
char *option;
|
||||
int32_t n,line=0;
|
||||
TFileStat fs;
|
||||
|
||||
if (!FileOpen(&f,filename,O_RDONLY))
|
||||
return FALSE;
|
||||
|
||||
while (ConfReadLine(&f,z,512))
|
||||
{
|
||||
line++;
|
||||
p=z;
|
||||
|
||||
if (ConfNextToken(&p)) {
|
||||
option=ConfGetToken(&p);
|
||||
if (option)
|
||||
{
|
||||
ConfNextToken(&p);
|
||||
|
||||
if (strcasecmp(option,"port")==0)
|
||||
{
|
||||
if (ConfReadInt(p,&n,1,65535))
|
||||
srv->port=n;
|
||||
else
|
||||
TraceExit("Invalid port '%s'",p);
|
||||
}
|
||||
else if (strcasecmp(option,"serverroot")==0)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
if (_chdir(p))
|
||||
#else
|
||||
if (chdir(p))
|
||||
#endif
|
||||
TraceExit("Invalid server root '%s'",p);
|
||||
}
|
||||
else if (strcasecmp(option,"path")==0)
|
||||
{
|
||||
if (FileStat(p,&fs))
|
||||
if (fs.st_mode & S_IFDIR)
|
||||
{
|
||||
free(srv->filespath);
|
||||
srv->filespath=strdup(p);
|
||||
continue;
|
||||
};
|
||||
|
||||
TraceExit("Invalid path '%s'",p);
|
||||
}
|
||||
else if (strcasecmp(option,"default")==0)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
while ((filename=ConfGetToken(&p)))
|
||||
{
|
||||
ListAdd(&srv->defaultfilenames,strdup(filename));
|
||||
if (!ConfNextToken(&p))
|
||||
break;
|
||||
};
|
||||
}
|
||||
else if (strcasecmp(option,"keepalive")==0)
|
||||
{
|
||||
if (ConfReadInt(p,&n,1,65535))
|
||||
srv->keepalivemaxconn=n;
|
||||
else
|
||||
TraceExit("Invalid KeepAlive value '%s'",p);
|
||||
}
|
||||
else if (strcasecmp(option,"timeout")==0)
|
||||
{
|
||||
if (ConfReadInt(p,&n,1,3600))
|
||||
{
|
||||
srv->keepalivetimeout=n;
|
||||
/* Must see what to do with that */
|
||||
srv->timeout=n;
|
||||
}
|
||||
else
|
||||
TraceExit("Invalid TimeOut value '%s'",p);
|
||||
}
|
||||
else if (strcasecmp(option,"mimetypes")==0)
|
||||
{
|
||||
if (!ConfReadMIMETypes(p))
|
||||
TraceExit("Can't read MIME Types file '%s'",p);
|
||||
}
|
||||
else if (strcasecmp(option,"logfile")==0)
|
||||
{
|
||||
LogOpen(srv,p);
|
||||
}
|
||||
else if (strcasecmp(option,"user")==0)
|
||||
{
|
||||
#ifdef _UNIX
|
||||
if (*p=='#')
|
||||
{
|
||||
int32_t n;
|
||||
|
||||
if (!ConfReadInt(p+1,&n,0,0))
|
||||
TraceExit("Bad user number '%s'",p);
|
||||
else
|
||||
srv->uid=n;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct passwd *pwd;
|
||||
|
||||
if (!(pwd=getpwnam(p)))
|
||||
TraceExit("Unknown user '%s'",p);
|
||||
|
||||
srv->uid=pwd->pw_uid;
|
||||
if ((int)srv->gid==(-1))
|
||||
srv->gid=pwd->pw_gid;
|
||||
};
|
||||
#else
|
||||
TraceMsg("User option ignored");
|
||||
#endif /* _UNIX */
|
||||
}
|
||||
else if (strcasecmp(option,"pidfile")==0)
|
||||
{
|
||||
#ifdef _UNIX
|
||||
if (!FileOpenCreate(&srv->pidfile,p,O_TRUNC | O_WRONLY))
|
||||
{
|
||||
srv->pidfile=-1;
|
||||
TraceMsg("Bad PidFile value '%s'",p);
|
||||
};
|
||||
#else
|
||||
TraceMsg("PidFile option ignored");
|
||||
#endif /* _UNIX */
|
||||
}
|
||||
else if (strcasecmp(option,"advertiseserver")==0)
|
||||
{
|
||||
if (!ConfReadBool(p,&srv->advertise))
|
||||
TraceExit("Invalid boolean value "
|
||||
"for AdvertiseServer option");
|
||||
}
|
||||
else
|
||||
TraceExit("Invalid option '%s' at line %d",option,line);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
FileClose(&f);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/*******************************************************************************
|
||||
**
|
||||
** conn.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
/*********************************************************************
|
||||
** Conn
|
||||
*********************************************************************/
|
||||
|
||||
TConn *ConnAlloc()
|
||||
{
|
||||
return (TConn *)malloc(sizeof(TConn));
|
||||
}
|
||||
|
||||
void ConnFree(TConn *c)
|
||||
{
|
||||
free(c);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
THREAD_ENTRYTYPE ConnJob(TConn *c) {
|
||||
c->connected=TRUE;
|
||||
(c->job)(c);
|
||||
c->connected=FALSE;
|
||||
ThreadExit( &c->thread, 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
abyss_bool ConnCreate2(TConn * const connectionP,
|
||||
TServer * const serverP,
|
||||
TSocket const connectedSocket,
|
||||
TIPAddr const peerIpAddr,
|
||||
void ( * func)(TConn *),
|
||||
enum abyss_foreback const foregroundBackground)
|
||||
{
|
||||
abyss_bool retval;
|
||||
|
||||
connectionP->server = serverP;
|
||||
connectionP->socket = connectedSocket;
|
||||
connectionP->peerip = peerIpAddr;
|
||||
connectionP->buffersize = 0;
|
||||
connectionP->bufferpos = 0;
|
||||
connectionP->connected = TRUE;
|
||||
connectionP->job = func;
|
||||
connectionP->inbytes = 0;
|
||||
connectionP->outbytes = 0;
|
||||
connectionP->trace = getenv("ABYSS_TRACE_CONN");
|
||||
|
||||
switch (foregroundBackground)
|
||||
{
|
||||
case ABYSS_FOREGROUND:
|
||||
connectionP->hasOwnThread = FALSE;
|
||||
retval = TRUE;
|
||||
break;
|
||||
case ABYSS_BACKGROUND:
|
||||
connectionP->hasOwnThread = TRUE;
|
||||
retval = ThreadCreate(&connectionP->thread,
|
||||
(TThreadProc)ConnJob,
|
||||
connectionP);
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
abyss_bool ConnCreate(TConn *c, TSocket *s, void (*func)(TConn *))
|
||||
{
|
||||
return ConnCreate2(c, c->server, *s, c->peerip, func, ABYSS_BACKGROUND);
|
||||
}
|
||||
|
||||
abyss_bool ConnProcess(TConn *c)
|
||||
{
|
||||
abyss_bool retval;
|
||||
|
||||
if (c->hasOwnThread) {
|
||||
/* There's a background thread to handle this connection. Set
|
||||
it running.
|
||||
*/
|
||||
retval = ThreadRun(&(c->thread));
|
||||
} else {
|
||||
/* No background thread. We just handle it here while Caller waits. */
|
||||
(c->job)(c);
|
||||
c->connected=FALSE;
|
||||
retval = TRUE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void ConnClose(TConn *c)
|
||||
{
|
||||
if (c->hasOwnThread)
|
||||
ThreadClose(&c->thread);
|
||||
}
|
||||
|
||||
abyss_bool ConnKill(TConn *c)
|
||||
{
|
||||
c->connected=FALSE;
|
||||
return ThreadKill(&(c->thread));
|
||||
}
|
||||
|
||||
void ConnReadInit(TConn *c)
|
||||
{
|
||||
if (c->buffersize>c->bufferpos)
|
||||
{
|
||||
c->buffersize-=c->bufferpos;
|
||||
memmove(c->buffer,c->buffer+c->bufferpos,c->buffersize);
|
||||
c->bufferpos=0;
|
||||
}
|
||||
else
|
||||
c->buffersize=c->bufferpos=0;
|
||||
|
||||
c->inbytes=c->outbytes=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
traceSocketRead(const char * const label,
|
||||
const char * const buffer,
|
||||
unsigned int const size) {
|
||||
|
||||
unsigned int nonPrintableCount;
|
||||
unsigned int i;
|
||||
|
||||
nonPrintableCount = 0; /* Initial value */
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (!isprint(buffer[i]) && buffer[i] != '\n' && buffer[i] != '\r')
|
||||
++nonPrintableCount;
|
||||
}
|
||||
if (nonPrintableCount > 0)
|
||||
fprintf(stderr, "%s contains %u nonprintable characters.\n",
|
||||
label, nonPrintableCount);
|
||||
|
||||
fprintf(stderr, "%s:\n", label);
|
||||
fprintf(stderr, "%.*s\n", (int)size, buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
ConnRead(TConn * const c,
|
||||
uint32_t const timeout) {
|
||||
|
||||
while (SocketWait(&(c->socket),TRUE,FALSE,timeout*1000) == 1) {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
|
||||
x = SocketAvailableReadBytes(&c->socket);
|
||||
|
||||
/* Avoid lost connections */
|
||||
if (x <= 0)
|
||||
break;
|
||||
|
||||
/* Avoid Buffer overflow and lost Connections */
|
||||
if (x + c->buffersize >= BUFFER_SIZE)
|
||||
x = BUFFER_SIZE-c->buffersize - 1;
|
||||
|
||||
y = SocketRead(&c->socket, c->buffer + c->buffersize, x);
|
||||
if (y > 0) {
|
||||
if (c->trace)
|
||||
traceSocketRead("READ FROM SOCKET:",
|
||||
c->buffer + c->buffersize, y);
|
||||
|
||||
c->inbytes += y;
|
||||
c->buffersize += y;
|
||||
c->buffer[c->buffersize] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool ConnWrite(TConn *c,void *buffer,uint32_t size)
|
||||
{
|
||||
char *buf = buffer;
|
||||
int rc, off = 0;
|
||||
|
||||
while (TRUE) {
|
||||
/* try sending data */
|
||||
if ((rc = SocketWrite(&(c->socket),&buf[off],size - off)) <= 0)
|
||||
return FALSE;
|
||||
|
||||
/* increase count */
|
||||
off += rc;
|
||||
|
||||
/* check we're not finished writing */
|
||||
if (off >= size)
|
||||
break;
|
||||
}
|
||||
|
||||
c->outbytes+=size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
abyss_bool ConnWriteFromFile(TConn *c,TFile *file,uint64_t start,uint64_t end,
|
||||
void *buffer,uint32_t buffersize,uint32_t rate)
|
||||
{
|
||||
uint64_t y,bytesread=0;
|
||||
uint32_t waittime;
|
||||
|
||||
if (rate>0)
|
||||
{
|
||||
if (buffersize>rate)
|
||||
buffersize=rate;
|
||||
|
||||
waittime=(1000*buffersize)/rate;
|
||||
}
|
||||
else
|
||||
waittime=0;
|
||||
|
||||
if (!FileSeek(file,start,SEEK_SET))
|
||||
return FALSE;
|
||||
|
||||
while (bytesread<=end-start)
|
||||
{
|
||||
y=(end-start+1)-bytesread;
|
||||
|
||||
if (y>buffersize)
|
||||
y=buffersize;
|
||||
|
||||
y=FileRead(file,buffer,y);
|
||||
bytesread+=y;
|
||||
|
||||
if (y>0)
|
||||
ConnWrite(c,buffer,y);
|
||||
else
|
||||
break;
|
||||
|
||||
if (waittime)
|
||||
ThreadWait(waittime);
|
||||
};
|
||||
|
||||
return (bytesread>end-start);
|
||||
}
|
||||
|
||||
abyss_bool ConnReadLine(TConn *c,char **z,uint32_t timeout)
|
||||
{
|
||||
char *p,*t;
|
||||
abyss_bool first=TRUE;
|
||||
uint32_t to,start;
|
||||
|
||||
p=*z=c->buffer+c->bufferpos;
|
||||
start=clock();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
to=(clock()-start)/CLOCKS_PER_SEC;
|
||||
if (to>timeout)
|
||||
break;
|
||||
|
||||
if (first)
|
||||
{
|
||||
if (c->bufferpos>=c->buffersize)
|
||||
if (!ConnRead(c,timeout-to))
|
||||
break;
|
||||
|
||||
first=FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ConnRead(c,timeout-to))
|
||||
break;
|
||||
};
|
||||
|
||||
t=strchr(p,LF);
|
||||
if (t)
|
||||
{
|
||||
if ((*p!=LF) && (*p!=CR))
|
||||
{
|
||||
if (!*(t+1))
|
||||
continue;
|
||||
|
||||
p=t;
|
||||
|
||||
if ((*(p+1)==' ') || (*(p+1)=='\t'))
|
||||
{
|
||||
if (p>*z)
|
||||
if (*(p-1)==CR)
|
||||
*(p-1)=' ';
|
||||
|
||||
*(p++)=' ';
|
||||
continue;
|
||||
};
|
||||
} else {
|
||||
/* emk - 04 Jan 2001 - Bug fix to leave buffer
|
||||
** pointing at start of body after reading blank
|
||||
** line following header. */
|
||||
p=t;
|
||||
}
|
||||
|
||||
c->bufferpos+=p+1-*z;
|
||||
|
||||
if (p>*z)
|
||||
if (*(p-1)==CR)
|
||||
p--;
|
||||
|
||||
*p='\0';
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,543 @@
|
||||
/******************************************************************************
|
||||
**
|
||||
** list.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mallocvar.h"
|
||||
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
#include "token.h"
|
||||
|
||||
/*********************************************************************
|
||||
** List
|
||||
*********************************************************************/
|
||||
|
||||
void ListInit(TList *sl)
|
||||
{
|
||||
sl->item=NULL;
|
||||
sl->size=sl->maxsize=0;
|
||||
sl->autofree=FALSE;
|
||||
}
|
||||
|
||||
void ListInitAutoFree(TList *sl)
|
||||
{
|
||||
sl->item=NULL;
|
||||
sl->size=sl->maxsize=0;
|
||||
sl->autofree=TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ListFree(TList * const sl) {
|
||||
|
||||
if (sl->item) {
|
||||
if (sl->autofree) {
|
||||
unsigned int i;
|
||||
for (i = sl->size; i > 0; --i)
|
||||
free(sl->item[i-1]);
|
||||
|
||||
}
|
||||
free(sl->item);
|
||||
}
|
||||
sl->item = NULL;
|
||||
sl->size = 0;
|
||||
sl->maxsize = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ListFreeItems(TList * const sl) {
|
||||
|
||||
if (sl->item) {
|
||||
unsigned int i;
|
||||
for (i = sl->size; i > 0; --i)
|
||||
free(sl->item[i-1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
ListAdd(TList * const sl,
|
||||
void * const str) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Add an item to the end of the list.
|
||||
-----------------------------------------------------------------------------*/
|
||||
abyss_bool success;
|
||||
|
||||
if (sl->size >= sl->maxsize) {
|
||||
uint16_t newSize = sl->maxsize + 16;
|
||||
void **newitem;
|
||||
|
||||
newitem = realloc(sl->item, newSize * sizeof(void *));
|
||||
if (newitem) {
|
||||
sl->item = newitem;
|
||||
sl->maxsize = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (sl->size >= sl->maxsize)
|
||||
success = FALSE;
|
||||
else {
|
||||
success = TRUE;
|
||||
sl->item[sl->size++] = str;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ListRemove(TList * const sl) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Remove the last item from the list.
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
assert(sl->size > 0);
|
||||
|
||||
--sl->size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
ListAddFromString(TList * const list,
|
||||
char * const stringArg) {
|
||||
|
||||
char *t,*p;
|
||||
char * c;
|
||||
|
||||
c = stringArg;
|
||||
|
||||
if (c)
|
||||
while (1)
|
||||
{
|
||||
NextToken(&c);
|
||||
|
||||
while (*c==',')
|
||||
c++;
|
||||
|
||||
if (!(t=GetToken(&c)))
|
||||
break;
|
||||
|
||||
p=c-2;
|
||||
|
||||
while (*p==',')
|
||||
*(p--)='\0';
|
||||
|
||||
if (*t)
|
||||
if (!ListAdd(list,t))
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
abyss_bool
|
||||
ListFindString(TList * const sl,
|
||||
char * const str,
|
||||
uint16_t * const indexP)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
if (sl->item && str)
|
||||
for (i=0;i<sl->size;i++)
|
||||
if (strcmp(str,(char *)(sl->item[i]))==0)
|
||||
{
|
||||
*indexP=i;
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
** Buffer
|
||||
*********************************************************************/
|
||||
|
||||
abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize)
|
||||
{
|
||||
/* ************** Implement the static buffers ***/
|
||||
buf->staticid=0;
|
||||
buf->data=(void *)malloc(memsize);
|
||||
if (buf->data)
|
||||
{
|
||||
buf->size=memsize;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->size=0;
|
||||
return FALSE;
|
||||
};
|
||||
}
|
||||
|
||||
void BufferFree(TBuffer *buf)
|
||||
{
|
||||
if (buf->staticid)
|
||||
{
|
||||
/* ************** Implement the static buffers ***/
|
||||
}
|
||||
else
|
||||
free(buf->data);
|
||||
|
||||
buf->size=0;
|
||||
buf->staticid=0;
|
||||
}
|
||||
|
||||
abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize)
|
||||
{
|
||||
if (buf->staticid)
|
||||
{
|
||||
TBuffer b;
|
||||
|
||||
if (memsize<=buf->size)
|
||||
return TRUE;
|
||||
|
||||
if (BufferAlloc(&b,memsize))
|
||||
{
|
||||
memcpy(b.data,buf->data,buf->size);
|
||||
BufferFree(buf);
|
||||
*buf=b;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
void *d;
|
||||
|
||||
d=realloc(buf->data,memsize);
|
||||
if (d)
|
||||
{
|
||||
buf->data=d;
|
||||
buf->size=memsize;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
** String
|
||||
*********************************************************************/
|
||||
|
||||
abyss_bool StringAlloc(TString *s)
|
||||
{
|
||||
s->size=0;
|
||||
if (BufferAlloc(&(s->buffer),256))
|
||||
{
|
||||
*(char *)(s->buffer.data)='\0';
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
abyss_bool StringConcat(TString *s,char *s2)
|
||||
{
|
||||
uint32_t len=strlen(s2);
|
||||
|
||||
if (len+s->size+1>s->buffer.size)
|
||||
if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
|
||||
return FALSE;
|
||||
|
||||
strcat((char *)(s->buffer.data),s2);
|
||||
s->size+=len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
abyss_bool StringBlockConcat(TString *s,char *s2,char **ref)
|
||||
{
|
||||
uint32_t len=strlen(s2)+1;
|
||||
|
||||
if (len+s->size>s->buffer.size)
|
||||
if (!BufferRealloc(&(s->buffer),((len+s->size+1+256)/256)*256))
|
||||
return FALSE;
|
||||
|
||||
*ref=(char *)(s->buffer.data)+s->size;
|
||||
memcpy(*ref,s2,len);
|
||||
s->size+=len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void StringFree(TString *s)
|
||||
{
|
||||
s->size=0;
|
||||
BufferFree(&(s->buffer));
|
||||
}
|
||||
|
||||
char *StringData(TString *s)
|
||||
{
|
||||
return (char *)(s->buffer.data);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
** Hash
|
||||
*********************************************************************/
|
||||
|
||||
static uint16_t
|
||||
Hash16(const char * const start) {
|
||||
|
||||
const char * s;
|
||||
|
||||
uint16_t i;
|
||||
|
||||
s = start;
|
||||
i = 0;
|
||||
|
||||
while(*s)
|
||||
i = i * 37 + *s++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
** Table
|
||||
*********************************************************************/
|
||||
|
||||
void TableInit(TTable *t)
|
||||
{
|
||||
t->item=NULL;
|
||||
t->size=t->maxsize=0;
|
||||
}
|
||||
|
||||
void TableFree(TTable *t)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
if (t->item)
|
||||
{
|
||||
if (t->size)
|
||||
for (i=t->size;i>0;i--)
|
||||
{
|
||||
free(t->item[i-1].name);
|
||||
free(t->item[i-1].value);
|
||||
};
|
||||
|
||||
free(t->item);
|
||||
}
|
||||
|
||||
TableInit(t);
|
||||
}
|
||||
|
||||
abyss_bool TableFindIndex(TTable *t,char *name,uint16_t *index)
|
||||
{
|
||||
uint16_t i,hash=Hash16(name);
|
||||
|
||||
if ((t->item) && (t->size>0) && (*index<t->size))
|
||||
{
|
||||
for (i=*index;i<t->size;i++)
|
||||
if (hash==t->item[i].hash)
|
||||
if (strcmp(t->item[i].name,name)==0)
|
||||
{
|
||||
*index=i;
|
||||
return TRUE;
|
||||
};
|
||||
};
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
abyss_bool TableAddReplace(TTable *t,char *name,char *value)
|
||||
{
|
||||
uint16_t i=0;
|
||||
|
||||
if (TableFindIndex(t,name,&i))
|
||||
{
|
||||
free(t->item[i].value);
|
||||
if (value)
|
||||
t->item[i].value=strdup(value);
|
||||
else
|
||||
{
|
||||
free(t->item[i].name);
|
||||
if (--t->size>0)
|
||||
t->item[i]=t->item[t->size];
|
||||
};
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return TableAdd(t,name,value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
TableAdd(TTable *t,char *name,char *value) {
|
||||
|
||||
if (t->size>=t->maxsize) {
|
||||
TTableItem *newitem;
|
||||
|
||||
t->maxsize+=16;
|
||||
|
||||
newitem=(TTableItem *)realloc(t->item,(t->maxsize)*sizeof(TTableItem));
|
||||
if (newitem)
|
||||
t->item=newitem;
|
||||
else {
|
||||
t->maxsize-=16;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
t->item[t->size].name=strdup(name);
|
||||
t->item[t->size].value=strdup(value);
|
||||
t->item[t->size].hash=Hash16(name);
|
||||
|
||||
++t->size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char *TableFind(TTable *t,char *name)
|
||||
{
|
||||
uint16_t i=0;
|
||||
|
||||
if (TableFindIndex(t,name,&i))
|
||||
return t->item[i].value;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
** Pool
|
||||
*********************************************************************/
|
||||
|
||||
static TPoolZone *
|
||||
PoolZoneAlloc(uint32_t zonesize) {
|
||||
TPoolZone *pz;
|
||||
|
||||
pz=(TPoolZone *)malloc(zonesize+sizeof(TPoolZone));
|
||||
if (pz)
|
||||
{
|
||||
pz->pos=pz->data;
|
||||
pz->maxpos=pz->pos+zonesize;
|
||||
pz->next=pz->prev=NULL;
|
||||
};
|
||||
|
||||
return pz;
|
||||
}
|
||||
|
||||
abyss_bool PoolCreate(TPool *p,uint32_t zonesize)
|
||||
{
|
||||
p->zonesize=zonesize;
|
||||
if (MutexCreate(&p->mutex))
|
||||
if (!(p->firstzone=p->currentzone=PoolZoneAlloc(zonesize)))
|
||||
{
|
||||
MutexFree(&p->mutex);
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void *PoolAlloc(TPool *p,uint32_t size)
|
||||
{
|
||||
TPoolZone *pz,*npz;
|
||||
void *x;
|
||||
uint32_t zonesize;
|
||||
|
||||
if (size==0)
|
||||
return NULL;
|
||||
|
||||
if (!MutexLock(&p->mutex))
|
||||
return NULL;
|
||||
|
||||
pz=p->currentzone;
|
||||
|
||||
if (pz->pos+size<pz->maxpos)
|
||||
{
|
||||
x=pz->pos;
|
||||
pz->pos+=size;
|
||||
MutexUnlock(&p->mutex);
|
||||
return x;
|
||||
};
|
||||
|
||||
if (size>p->zonesize)
|
||||
zonesize=size;
|
||||
else
|
||||
zonesize=p->zonesize;
|
||||
|
||||
npz=PoolZoneAlloc(zonesize);
|
||||
if (npz)
|
||||
{
|
||||
npz->prev=pz;
|
||||
npz->next=pz->next;
|
||||
pz->next=npz;
|
||||
p->currentzone=npz;
|
||||
x=npz->data;
|
||||
npz->pos=npz->data+size;
|
||||
}
|
||||
else
|
||||
x=NULL;
|
||||
|
||||
MutexUnlock(&p->mutex);
|
||||
return x;
|
||||
}
|
||||
|
||||
void PoolFree(TPool *p)
|
||||
{
|
||||
TPoolZone *pz,*npz;
|
||||
|
||||
pz=p->firstzone;
|
||||
|
||||
while (pz)
|
||||
{
|
||||
npz=pz->next;
|
||||
free(pz);
|
||||
pz=npz;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *PoolStrdup(TPool *p,char *s) {
|
||||
|
||||
char *ns;
|
||||
|
||||
if (s) {
|
||||
ns = PoolAlloc(p, strlen(s) + 1);
|
||||
if (ns)
|
||||
strcpy(ns, s);
|
||||
} else
|
||||
ns = NULL;
|
||||
|
||||
return ns;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/******************************************************************************
|
||||
**
|
||||
** file.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ABYSS_WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
/* Must check this
|
||||
#include <sys/io.h>
|
||||
*/
|
||||
#endif /* ABYSS_WIN32 */
|
||||
|
||||
#ifndef ABYSS_WIN32
|
||||
#include <dirent.h>
|
||||
#endif /* ABYSS_WIN32 */
|
||||
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
/*********************************************************************
|
||||
** File
|
||||
*********************************************************************/
|
||||
|
||||
abyss_bool FileOpen(TFile *f, const char *name,uint32_t attrib)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return ((*f=_open(name,attrib))!=(-1));
|
||||
#else
|
||||
return ((*f=open(name,attrib))!=(-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
abyss_bool FileOpenCreate(TFile *f, const char *name, uint32_t attrib)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return ((*f=_open(name,attrib | O_CREAT,_S_IWRITE | _S_IREAD))!=(-1));
|
||||
#else
|
||||
return ((*f=open(name,attrib | O_CREAT,S_IWRITE | S_IREAD))!=(-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
abyss_bool FileWrite(TFile *f, void *buffer, uint32_t len)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return (_write(*f,buffer,len)==(int32_t)len);
|
||||
#else
|
||||
return (write(*f,buffer,len)==(int32_t)len);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t FileRead(TFile *f, void *buffer, uint32_t len)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return (_read(*f,buffer,len));
|
||||
#else
|
||||
return (read(*f,buffer,len));
|
||||
#endif
|
||||
}
|
||||
|
||||
abyss_bool FileSeek(TFile *f, uint64_t pos, uint32_t attrib)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return (_lseek(*f,pos,attrib)!=(-1));
|
||||
#else
|
||||
return (lseek(*f,pos,attrib)!=(-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t FileSize(TFile *f)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return (_filelength(*f));
|
||||
#else
|
||||
struct stat fs;
|
||||
|
||||
fstat(*f,&fs);
|
||||
return (fs.st_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
abyss_bool FileClose(TFile *f)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return (_close(*f)!=(-1));
|
||||
#else
|
||||
return (close(*f)!=(-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
abyss_bool FileStat(char *filename,TFileStat *filestat)
|
||||
{
|
||||
#if defined( ABYSS_WIN32 ) && !defined( __BORLANDC__ )
|
||||
return (_stati64(filename,filestat)!=(-1));
|
||||
#else
|
||||
return (stat(filename,filestat)!=(-1));
|
||||
#endif
|
||||
}
|
||||
|
||||
abyss_bool FileFindFirst(TFileFind *filefind,char *path,TFileInfo *fileinfo)
|
||||
{
|
||||
#ifdef ABYSS_WIN32
|
||||
abyss_bool ret;
|
||||
char *p=path+strlen(path);
|
||||
|
||||
*p='\\';
|
||||
*(p+1)='*';
|
||||
*(p+2)='\0';
|
||||
#ifndef __BORLANDC__
|
||||
ret=(((*filefind)=_findfirst(path,fileinfo))!=(-1));
|
||||
#else
|
||||
*filefind = FindFirstFile( path, &fileinfo->data );
|
||||
ret = *filefind != NULL;
|
||||
if( ret )
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.LowPart = fileinfo->data.nFileSizeLow;
|
||||
li.HighPart = fileinfo->data.nFileSizeHigh;
|
||||
strcpy( fileinfo->name, fileinfo->data.cFileName );
|
||||
fileinfo->attrib = fileinfo->data.dwFileAttributes;
|
||||
fileinfo->size = li.QuadPart;
|
||||
fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
|
||||
}
|
||||
#endif
|
||||
*p='\0';
|
||||
return ret;
|
||||
#else
|
||||
strncpy(filefind->path,path,NAME_MAX);
|
||||
filefind->path[NAME_MAX]='\0';
|
||||
filefind->handle=opendir(path);
|
||||
if (filefind->handle)
|
||||
return FileFindNext(filefind,fileinfo);
|
||||
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
abyss_bool FileFindNext(TFileFind *filefind,TFileInfo *fileinfo)
|
||||
{
|
||||
#ifdef ABYSS_WIN32
|
||||
|
||||
#ifndef __BORLANDC__
|
||||
return (_findnext(*filefind,fileinfo)!=(-1));
|
||||
#else
|
||||
abyss_bool ret = FindNextFile( *filefind, &fileinfo->data );
|
||||
if( ret )
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.LowPart = fileinfo->data.nFileSizeLow;
|
||||
li.HighPart = fileinfo->data.nFileSizeHigh;
|
||||
strcpy( fileinfo->name, fileinfo->data.cFileName );
|
||||
fileinfo->attrib = fileinfo->data.dwFileAttributes;
|
||||
fileinfo->size = li.QuadPart;
|
||||
fileinfo->time_write = fileinfo->data.ftLastWriteTime.dwLowDateTime;
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#else
|
||||
struct dirent *de;
|
||||
/****** Must be changed ***/
|
||||
char z[NAME_MAX+1];
|
||||
|
||||
de=readdir(filefind->handle);
|
||||
if (de)
|
||||
{
|
||||
struct stat fs;
|
||||
|
||||
strcpy(fileinfo->name,de->d_name);
|
||||
strcpy(z,filefind->path);
|
||||
strncat(z,"/",NAME_MAX);
|
||||
strncat(z,fileinfo->name,NAME_MAX);
|
||||
z[NAME_MAX]='\0';
|
||||
|
||||
stat(z,&fs);
|
||||
|
||||
if (fs.st_mode & S_IFDIR)
|
||||
fileinfo->attrib=A_SUBDIR;
|
||||
else
|
||||
fileinfo->attrib=0;
|
||||
|
||||
fileinfo->size=fs.st_size;
|
||||
fileinfo->time_write=fs.st_mtime;
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileFindClose(TFileFind *filefind)
|
||||
{
|
||||
#ifdef ABYSS_WIN32
|
||||
|
||||
#ifndef __BORLANDC__
|
||||
_findclose(*filefind);
|
||||
#else
|
||||
FindClose( *filefind );
|
||||
#endif
|
||||
|
||||
#else
|
||||
closedir(filefind->handle);
|
||||
#endif
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,294 @@
|
||||
/******************************************************************************
|
||||
**
|
||||
** main.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef ABYSS_WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
/* Must check this
|
||||
#include <sys/io.h>
|
||||
*/
|
||||
#endif /* ABYSS_WIN32 */
|
||||
|
||||
#ifdef _UNIX
|
||||
#include <sys/signal.h>
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
void Answer(TSession *r, uint16_t statuscode, char *buffer)
|
||||
{
|
||||
ResponseChunked(r);
|
||||
|
||||
ResponseStatus(r,statuscode);
|
||||
|
||||
ResponseContentType(r,"text/html");
|
||||
|
||||
ResponseWrite(r);
|
||||
|
||||
HTTPWrite(r,"<HTML><BODY>",12);
|
||||
|
||||
HTTPWrite(r,buffer,strlen(buffer));
|
||||
|
||||
HTTPWrite(r,"</BODY></HTML>",14);
|
||||
|
||||
HTTPWriteEnd(r);
|
||||
}
|
||||
|
||||
abyss_bool HandleTime(TSession *r)
|
||||
{
|
||||
char z[50];
|
||||
time_t ltime;
|
||||
TDate date;
|
||||
|
||||
if (strcmp(r->uri,"/time")!=0)
|
||||
return FALSE;
|
||||
|
||||
if (!RequestAuth(r,"Mot de passe","moez","hello"))
|
||||
return TRUE;
|
||||
|
||||
time( <ime );
|
||||
DateFromGMT(&date,ltime);
|
||||
|
||||
|
||||
strcpy(z,"The time is ");
|
||||
DateToString(&date,z+strlen(z));
|
||||
|
||||
Answer(r,200,z);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
abyss_bool HandleDump(TSession *r)
|
||||
{
|
||||
char z[50];
|
||||
|
||||
if (strcmp(r->uri,"/name")!=0)
|
||||
return FALSE;
|
||||
|
||||
sprintf(z,"Server name is %s", (r->server)->name );
|
||||
Answer(r,200,z);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
abyss_bool HandleStatus(TSession *r)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
if (sscanf(r->uri,"/status/%d",&status)<=0)
|
||||
return FALSE;
|
||||
|
||||
ResponseStatus(r,(uint16_t)status);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
abyss_bool HandleMIMEType(TSession *r)
|
||||
{
|
||||
char *m;
|
||||
|
||||
if (strncmp(r->uri,"/mime/",6)!=0)
|
||||
return FALSE;
|
||||
|
||||
m=MIMETypeFromExt(r->uri+6);
|
||||
if (!m)
|
||||
m="(none)";
|
||||
|
||||
Answer(r,200,m);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef _UNIX
|
||||
static void sigterm(int sig)
|
||||
{
|
||||
TraceExit("Signal %d received. Exiting...\n",sig);
|
||||
}
|
||||
|
||||
static void sigchld(int sig)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
/* Reap defunct children until there aren't any more. */
|
||||
for (;;)
|
||||
{
|
||||
pid = waitpid( (pid_t) -1, &status, WNOHANG );
|
||||
|
||||
/* none left */
|
||||
if (pid==0)
|
||||
break;
|
||||
|
||||
if (pid<0)
|
||||
{
|
||||
/* because of ptrace */
|
||||
if (errno==EINTR)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif _UNIX
|
||||
|
||||
void copyright()
|
||||
{
|
||||
printf("ABYSS Web Server version "SERVER_VERSION"\n(C) Moez Mahfoudh - 2000\n\n");
|
||||
}
|
||||
|
||||
void help(char *name)
|
||||
{
|
||||
copyright();
|
||||
printf("Usage: %s [-h] [-c configuration file]\n\n",name);
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
TServer srv;
|
||||
char *p,*conffile=DEFAULT_CONF_FILE;
|
||||
abyss_bool err=FALSE;
|
||||
char *name=argv[0];
|
||||
|
||||
while (p=*(++argv))
|
||||
{
|
||||
if ((*p=='-') && (*(p+1)))
|
||||
if (*(p+2)=='\0')
|
||||
switch (*(p+1))
|
||||
{
|
||||
case 'c':
|
||||
argv++;
|
||||
if (*argv)
|
||||
conffile=*argv;
|
||||
else
|
||||
err=TRUE;
|
||||
break;
|
||||
case 'h':
|
||||
help(name);
|
||||
exit(0);
|
||||
default:
|
||||
err=TRUE;
|
||||
}
|
||||
else
|
||||
err=TRUE;
|
||||
else
|
||||
err=TRUE;
|
||||
};
|
||||
|
||||
if (err)
|
||||
{
|
||||
help(name);
|
||||
exit(1);
|
||||
};
|
||||
|
||||
#ifdef ABYSS_WIN32
|
||||
copyright();
|
||||
printf("\nPress Ctrl+C to stop the server\n");
|
||||
#endif
|
||||
|
||||
DateInit();
|
||||
|
||||
MIMETypeInit();
|
||||
|
||||
ServerCreate(&srv,"HTTPServer",80,DEFAULT_DOCS,NULL);
|
||||
|
||||
ConfReadServerFile(conffile,&srv);
|
||||
|
||||
ServerAddHandler(&srv,HandleTime);
|
||||
ServerAddHandler(&srv,HandleDump);
|
||||
ServerAddHandler(&srv,HandleStatus);
|
||||
ServerAddHandler(&srv,HandleMIMEType);
|
||||
|
||||
ServerInit(&srv);
|
||||
|
||||
#ifdef _UNIX
|
||||
/* Catch various termination signals. */
|
||||
signal(SIGTERM,sigterm);
|
||||
signal(SIGINT,sigterm);
|
||||
signal(SIGHUP,sigterm);
|
||||
signal(SIGUSR1,sigterm);
|
||||
|
||||
/* Catch defunct children. */
|
||||
signal(SIGCHLD,sigchld);
|
||||
/* Become a daemon */
|
||||
switch (fork())
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
TraceExit("Unable to become a daemon");
|
||||
default:
|
||||
exit(0);
|
||||
};
|
||||
|
||||
#if !defined( _NO_USERS ) && !defined( __CYGWIN32__ )
|
||||
setsid();
|
||||
/* Change the current user if we are root */
|
||||
if (getuid()==0)
|
||||
{
|
||||
if (srv.uid==(-1))
|
||||
TraceExit("Can't run under root privileges. Please add a User option in your configuration file.");
|
||||
|
||||
if (setgroups(0,NULL)==(-1))
|
||||
TraceExit("Failed to setup the group.");
|
||||
|
||||
if (srv.gid!=(-1))
|
||||
if (setgid(srv.gid)==(-1))
|
||||
TraceExit("Failed to change the group.");
|
||||
|
||||
if (setuid(srv.uid)==(-1))
|
||||
TraceExit("Failed to change the user.");
|
||||
};
|
||||
#endif
|
||||
|
||||
if (srv.pidfile!=(-1))
|
||||
{
|
||||
char z[16];
|
||||
|
||||
sprintf(z,"%d",getpid());
|
||||
FileWrite(&srv.pidfile,z,strlen(z));
|
||||
FileClose(&srv.pidfile);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
ServerRun(&srv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,269 @@
|
||||
/******************************************************************************
|
||||
**
|
||||
** socket.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
******************************************************************************/
|
||||
|
||||
#include "xmlrpc_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_FILIO_H
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
#ifdef ABYSS_WIN32
|
||||
#define EINTR WSAEINTR
|
||||
#endif
|
||||
|
||||
static abyss_bool ABYSS_TRACE_SOCKET;
|
||||
|
||||
/*********************************************************************
|
||||
** Socket
|
||||
*********************************************************************/
|
||||
|
||||
abyss_bool SocketInit()
|
||||
{
|
||||
abyss_bool retval;
|
||||
#ifdef ABYSS_WIN32
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
wVersionRequested = MAKEWORD( 2, 0 );
|
||||
|
||||
err = WSAStartup( wVersionRequested, &wsaData );
|
||||
retval = ( err == 0 );
|
||||
#else
|
||||
retval = TRUE;
|
||||
ABYSS_TRACE_SOCKET = (getenv("ABYSS_TRACE_SOCKET") != NULL);
|
||||
#endif /* ABYSS_WIN32 */
|
||||
if (ABYSS_TRACE_SOCKET)
|
||||
fprintf(stderr, "Abyss socket layer will trace socket traffic "
|
||||
"due to ABYSS_TRACE_SOCKET environment variable\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
#define RET(x) return ((x)!=(-1))
|
||||
|
||||
abyss_bool SocketCreate(TSocket *s)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc =socket(AF_INET,SOCK_STREAM,0);
|
||||
if (rc < 0)
|
||||
return FALSE;
|
||||
else {
|
||||
int32_t n=1;
|
||||
*s = rc;
|
||||
RET(setsockopt(*s,SOL_SOCKET,SO_REUSEADDR,(char*)&n,sizeof(n)));
|
||||
}
|
||||
}
|
||||
|
||||
abyss_bool SocketClose(TSocket *s)
|
||||
{
|
||||
#ifdef ABYSS_WIN32
|
||||
RET(closesocket(*s));
|
||||
#else
|
||||
RET(close(*s));
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
int SocketWrite(TSocket *s, char *buffer, uint32_t len)
|
||||
{
|
||||
return send(*s,buffer,len,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t SocketRead(TSocket * const socketP,
|
||||
char * const buffer,
|
||||
uint32_t const len) {
|
||||
int rc;
|
||||
rc = recv(*socketP, buffer, len, 0);
|
||||
if (ABYSS_TRACE_SOCKET) {
|
||||
if (rc < 0)
|
||||
fprintf(stderr, "Abyss socket: recv() failed. errno=%d (%s)",
|
||||
errno, strerror(errno));
|
||||
else
|
||||
fprintf(stderr, "Abyss socket: read %u bytes: '%.*s'\n",
|
||||
len, (int)len, buffer);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t SocketPeek(TSocket *s, char *buffer, uint32_t len)
|
||||
{
|
||||
int32_t r=recv(*s,buffer,len,MSG_PEEK);
|
||||
|
||||
if (r==(-1))
|
||||
#ifdef ABYSS_WIN32
|
||||
if (SocketError()==WSAEMSGSIZE)
|
||||
#else
|
||||
if (SocketError()==EMSGSIZE)
|
||||
#endif
|
||||
return len;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
abyss_bool SocketConnect(TSocket *s, TIPAddr *addr, uint16_t port)
|
||||
{
|
||||
struct sockaddr_in name;
|
||||
|
||||
name.sin_family=AF_INET;
|
||||
name.sin_port=htons(port);
|
||||
name.sin_addr=*addr;
|
||||
|
||||
RET(connect(*s,(struct sockaddr *)&name,sizeof(name)));
|
||||
}
|
||||
|
||||
abyss_bool SocketBind(TSocket *s, TIPAddr *addr, uint16_t port)
|
||||
{
|
||||
struct sockaddr_in name;
|
||||
|
||||
name.sin_family=AF_INET;
|
||||
name.sin_port=htons(port);
|
||||
if (addr)
|
||||
name.sin_addr=*addr;
|
||||
else
|
||||
name.sin_addr.s_addr=INADDR_ANY;
|
||||
|
||||
RET(bind(*s,(struct sockaddr *)&name,sizeof(name)));
|
||||
}
|
||||
|
||||
abyss_bool SocketListen(TSocket *s, uint32_t backlog)
|
||||
{
|
||||
int32_t n=-1;
|
||||
|
||||
/* Disable the naggle algorithm to make persistant connections faster */
|
||||
setsockopt(*s, IPPROTO_TCP,TCP_NODELAY,(char *)&n,sizeof(n));
|
||||
|
||||
RET(listen(*s,backlog));
|
||||
}
|
||||
|
||||
abyss_bool SocketAccept(TSocket *s, TSocket *ns,TIPAddr *ip)
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
socklen_t size=sizeof(sa);
|
||||
abyss_bool connected;
|
||||
|
||||
connected = FALSE;
|
||||
for (;;) {
|
||||
int rc;
|
||||
rc = accept(*s,(struct sockaddr *)&sa,&size);
|
||||
if (rc >= 0)
|
||||
{
|
||||
connected = TRUE;
|
||||
*ns = rc;
|
||||
*ip=sa.sin_addr;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (SocketError()!=EINTR)
|
||||
break;
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
uint32_t SocketWait(TSocket *s,abyss_bool rd,abyss_bool wr,uint32_t timems)
|
||||
{
|
||||
fd_set rfds,wfds;
|
||||
#ifdef ABYSS_WIN32
|
||||
TIMEVAL tv;
|
||||
#else
|
||||
struct timeval tv;
|
||||
#endif /* ABYSS_WIN32 */
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
|
||||
if (rd)
|
||||
FD_SET(*s,&rfds);
|
||||
|
||||
if (wr)
|
||||
FD_SET(*s,&wfds);
|
||||
|
||||
tv.tv_sec=timems/1000;
|
||||
tv.tv_usec=timems%1000;
|
||||
|
||||
|
||||
for (;;)
|
||||
switch(select((*s)+1,&rfds,&wfds,NULL,
|
||||
(timems==TIME_INFINITE?NULL:&tv)))
|
||||
{
|
||||
case 0: /* time out */
|
||||
return 0;
|
||||
|
||||
case (-1): /* socket error */
|
||||
if (SocketError()==EINTR)
|
||||
break;
|
||||
|
||||
return 0;
|
||||
|
||||
default:
|
||||
if (FD_ISSET(*s,&rfds))
|
||||
return 1;
|
||||
if (FD_ISSET(*s,&wfds))
|
||||
return 2;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
abyss_bool SocketBlocking(TSocket *s, abyss_bool b)
|
||||
{
|
||||
uint32_t x=b;
|
||||
|
||||
RET(ioctlsocket(*s,FIONBIO,&x));
|
||||
}
|
||||
|
||||
uint32_t SocketAvailableReadBytes(TSocket *s)
|
||||
{
|
||||
uint32_t x;
|
||||
|
||||
if (ioctlsocket(*s,FIONREAD,&x)!=0)
|
||||
x=0;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t SocketError()
|
||||
{
|
||||
#ifdef ABYSS_WIN32
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
/*******************************************************************************
|
||||
**
|
||||
** thread.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
#ifdef ABYSS_WIN32
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
#include "xmlrpc_config.h"
|
||||
|
||||
/* 16K is the minimum size of stack on Win32 */
|
||||
#define THREAD_STACK_SIZE (16*1024)
|
||||
|
||||
/*********************************************************************
|
||||
** Thread
|
||||
*********************************************************************/
|
||||
|
||||
abyss_bool ThreadCreate(TThread * const t ATTR_UNUSED,
|
||||
TThreadProc const func,
|
||||
void * const arg )
|
||||
{
|
||||
#ifdef ABYSS_WIN32
|
||||
DWORD z;
|
||||
*t =(TThread)_beginthreadex( NULL, THREAD_STACK_SIZE, func,
|
||||
arg, CREATE_SUSPENDED, &z );
|
||||
return (*t!=NULL);
|
||||
#else
|
||||
# ifdef _UNIX
|
||||
# ifdef _THREAD
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init( &attr );
|
||||
pthread_attr_setstacksize( &attr, THREAD_STACK_SIZE );
|
||||
if( pthread_create( t,&attr,(PTHREAD_START_ROUTINE)func,arg)==0)
|
||||
{
|
||||
pthread_attr_destroy( &attr );
|
||||
return (pthread_detach(*t)==0);
|
||||
}
|
||||
pthread_attr_destroy( &attr );
|
||||
return FALSE;
|
||||
}
|
||||
# else
|
||||
switch (fork())
|
||||
{
|
||||
case 0:
|
||||
(*func)(arg);
|
||||
exit(0);
|
||||
case (-1):
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
return TRUE;
|
||||
# endif /* _THREAD */
|
||||
# else
|
||||
(*func)(arg);
|
||||
return TRUE;
|
||||
# endif /*_UNIX */
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
abyss_bool
|
||||
ThreadRun(TThread * const t ATTR_UNUSED) {
|
||||
#ifdef ABYSS_WIN32
|
||||
return (ResumeThread(*t)!=0xFFFFFFFF);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
ThreadStop(TThread * const t ATTR_UNUSED) {
|
||||
#ifdef ABYSS_WIN32
|
||||
return (SuspendThread(*t)!=0xFFFFFFFF);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
ThreadKill(TThread * const t ATTR_UNUSED) {
|
||||
#ifdef ABYSS_WIN32
|
||||
return (TerminateThread(*t,0)!=0);
|
||||
#else
|
||||
/*return (pthread_kill(*t)==0);*/
|
||||
return TRUE;
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ThreadWait(uint32_t ms)
|
||||
{
|
||||
#ifdef ABYSS_WIN32
|
||||
Sleep(ms);
|
||||
#else
|
||||
usleep(ms*1000);
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ThreadExit(TThread * const t ATTR_UNUSED,
|
||||
int const ret_value ATTR_UNUSED) {
|
||||
#ifdef ABYSS_WIN32
|
||||
_endthreadex(ret_value);
|
||||
#elif defined(_THREAD)
|
||||
pthread_exit(&ret_value);
|
||||
#else
|
||||
;
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ThreadClose(TThread * const t ATTR_UNUSED) {
|
||||
#ifdef ABYSS_WIN32
|
||||
CloseHandle(*t);
|
||||
#endif /* ABYSS_WIN32 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
** Mutex
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
MutexCreate(TMutex * const m ATTR_UNUSED) {
|
||||
#if defined(ABYSS_WIN32)
|
||||
return ((*m=CreateMutex(NULL,FALSE,NULL))!=NULL);
|
||||
#elif defined(_THREAD)
|
||||
return (pthread_mutex_init(m, NULL)==0);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
MutexLock(TMutex * const m ATTR_UNUSED) {
|
||||
#if defined(ABYSS_WIN32)
|
||||
return (WaitForSingleObject(*m,INFINITE)!=WAIT_TIMEOUT);
|
||||
#elif defined(_THREAD)
|
||||
return (pthread_mutex_lock(m)==0);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
MutexUnlock(TMutex * const m ATTR_UNUSED) {
|
||||
#if defined(ABYSS_WIN32)
|
||||
return ReleaseMutex(*m);
|
||||
#elif defined(_THREAD)
|
||||
return (pthread_mutex_unlock(m)==0);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
abyss_bool
|
||||
MutexTryLock(TMutex * const m ATTR_UNUSED) {
|
||||
#if defined(ABYSS_WIN32)
|
||||
return (WaitForSingleObject(*m,0)!=WAIT_TIMEOUT);
|
||||
#elif defined(_THREAD)
|
||||
return (pthread_mutex_trylock(m)==0);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
MutexFree(TMutex * const m ATTR_UNUSED) {
|
||||
#if defined(ABYSS_WIN32)
|
||||
CloseHandle(*m);
|
||||
#elif defined(_THREAD)
|
||||
pthread_mutex_destroy(m);
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
#include "token.h"
|
||||
|
||||
void
|
||||
NextToken(char ** const p) {
|
||||
|
||||
abyss_bool gotToken;
|
||||
|
||||
gotToken = FALSE;
|
||||
|
||||
while (!gotToken) {
|
||||
switch (**p) {
|
||||
case '\t':
|
||||
case ' ':
|
||||
++(*p);
|
||||
break;
|
||||
default:
|
||||
gotToken = TRUE;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *
|
||||
GetToken(char ** const p) {
|
||||
|
||||
char * p0;
|
||||
|
||||
p0 = *p;
|
||||
|
||||
while (1) {
|
||||
switch (**p) {
|
||||
case '\t':
|
||||
case ' ':
|
||||
case CR:
|
||||
case LF:
|
||||
case '\0':
|
||||
if (p0 == *p)
|
||||
return NULL;
|
||||
|
||||
if (**p) {
|
||||
**p = '\0';
|
||||
++(*p);
|
||||
};
|
||||
return p0;
|
||||
|
||||
default:
|
||||
++(*p);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef ABYSS_TOKEN_H_INCLUDED
|
||||
#define ABYSS_TOKEN_H_INCLUDED
|
||||
|
||||
void
|
||||
NextToken(char ** const p);
|
||||
|
||||
char *
|
||||
GetToken(char ** const p);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/******************************************************************************
|
||||
**
|
||||
** trace.c
|
||||
**
|
||||
** This file is part of the ABYSS Web server project.
|
||||
**
|
||||
** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "xmlrpc-c/abyss.h"
|
||||
|
||||
/*********************************************************************
|
||||
** Tracing functions
|
||||
*********************************************************************/
|
||||
|
||||
static void
|
||||
TraceVMsg(char *fmt,va_list argptr) {
|
||||
vprintf(fmt,argptr);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void TraceMsg(char *fmt,...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr,fmt);
|
||||
TraceVMsg(fmt,argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void TraceExit(char *fmt,...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr,fmt);
|
||||
TraceVMsg(fmt,argptr);
|
||||
va_end(argptr);
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0.3 (03/23/2000)
|
||||
@@ -0,0 +1,46 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../..
|
||||
endif
|
||||
|
||||
include $(SRCDIR)/Makefile.config
|
||||
|
||||
CURL_INCLUDES := $(shell curl-config --cflags)
|
||||
# We expect that curl-config --cflags just gives us -I options, because
|
||||
# we need just the -I options for 'make dep'. Plus, it's scary to think
|
||||
# of what any other compiler flag would do to our compile.
|
||||
|
||||
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
|
||||
LDFLAGS = -lpthread $(LADD)
|
||||
|
||||
INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
|
||||
$(CURL_INCLUDES)
|
||||
|
||||
default: all
|
||||
|
||||
.PHONY: all
|
||||
all: xmlrpc_curl_transport.lo
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-common
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean distclean-common
|
||||
|
||||
.PHONY: tags
|
||||
tags: TAGS
|
||||
|
||||
.PHONY: distdir
|
||||
distdir:
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
|
||||
.PHONY: dep
|
||||
dep: dep-common
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
include Makefile.depend
|
||||
|
||||
xmlrpc_curl_transport.lo:%.lo:%.c
|
||||
$(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
|
||||
@@ -0,0 +1,971 @@
|
||||
/*=============================================================================
|
||||
xmlrpc_curl_transport
|
||||
===============================================================================
|
||||
Curl-based client transport for Xmlrpc-c
|
||||
|
||||
By Bryan Henderson 04.12.10.
|
||||
|
||||
Contributed to the public domain by its author.
|
||||
=============================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Curl global variables:
|
||||
|
||||
Curl maintains some minor information in process-global variables.
|
||||
One must call curl_global_init() to initialize them before calling
|
||||
any other Curl library function.
|
||||
|
||||
But note that one of those global variables tells that
|
||||
curl_global_init() has been called, and if you call it again,
|
||||
it's just a no-op. So we can call it for each of many transport
|
||||
object constructors.
|
||||
|
||||
The actual global variables appear to be constant so that it's OK
|
||||
for them to be shared among multiple objects and threads. And we never
|
||||
want other than the defaults. They're things like the identity of
|
||||
the malloc routine.
|
||||
|
||||
Note that not only could many Xmlrpc-c Curl XML transport
|
||||
objects be using Curl in the same process, but the Xmlrpc-c user may
|
||||
have uses of his own. So this whole fragile thing works only as long
|
||||
as the user doesn't need to set these global variables to something
|
||||
different from the defaults (because those are what we use).
|
||||
|
||||
curl_global_cleanup() reverts the process back to a state in which
|
||||
nobody can use the Curl library. So we can't ever call it. This
|
||||
means there will be some memory leakage, but since curl_global_init
|
||||
only ever has effect once, the amount of leakage is trivial. The
|
||||
user can do his own curl_global_cleanup() if he really cares.
|
||||
|
||||
Some of the Curl global variables are actually the SSL library global
|
||||
variables. The SSL library has the same disease.
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "xmlrpc_config.h"
|
||||
|
||||
#include "bool.h"
|
||||
#include "mallocvar.h"
|
||||
#include "linklist.h"
|
||||
#include "sstring.h"
|
||||
#include "casprintf.h"
|
||||
#include "pthreadx.h"
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base_int.h"
|
||||
#include "xmlrpc-c/client.h"
|
||||
#include "xmlrpc-c/client_int.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <curl/types.h>
|
||||
#include <curl/easy.h>
|
||||
|
||||
#if defined (WIN32) && defined(_DEBUG)
|
||||
# include <crtdbg.h>
|
||||
# define new DEBUG_NEW
|
||||
# define malloc(size) _malloc_dbg( size, _NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
# undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif /*WIN32 && _DEBUG*/
|
||||
|
||||
|
||||
|
||||
struct xmlrpc_client_transport {
|
||||
pthread_mutex_t listLock;
|
||||
struct list_head rpcList;
|
||||
/* List of all RPCs that exist for this transport. An RPC exists
|
||||
from the time the user requests it until the time the user
|
||||
acknowledges it is done.
|
||||
*/
|
||||
CURL * syncCurlSessionP;
|
||||
/* Handle for a Curl library session object that we use for
|
||||
all synchronous RPCs. An async RPC has one of its own,
|
||||
and consequently does not share things such as persistent
|
||||
connections and cookies with any other RPC.
|
||||
*/
|
||||
pthread_mutex_t syncCurlSessionLock;
|
||||
/* Hold this lock while accessing or using *syncCurlSessionP.
|
||||
You're using the session from the time you set any
|
||||
attributes in it or start a transaction with it until any
|
||||
transaction has finished and you've lost interest in any
|
||||
attributes of the session.
|
||||
*/
|
||||
const char * networkInterface;
|
||||
/* This identifies the network interface on the local side to
|
||||
use for the session. It is an ASCIIZ string in the form
|
||||
that the Curl recognizes for setting its CURLOPT_INTERFACE
|
||||
option (also the --interface option of the Curl program).
|
||||
E.g. "9.1.72.189" or "giraffe-data.com" or "eth0".
|
||||
|
||||
It isn't necessarily valid, but it does have a terminating NUL.
|
||||
|
||||
NULL means we have no preference.
|
||||
*/
|
||||
xmlrpc_bool sslVerifyPeer;
|
||||
/* In an SSL connection, we should authenticate the server's SSL
|
||||
certificate -- refuse to talk to him if it isn't authentic.
|
||||
This is equivalent to Curl's CURLOPT_SSL_VERIFY_PEER option.
|
||||
*/
|
||||
xmlrpc_bool sslVerifyHost;
|
||||
/* In an SSL connection, we should verify that the server's
|
||||
certificate (independently of whether the certificate is
|
||||
authentic) indicates the host name that is in the URL we
|
||||
are using for the server.
|
||||
*/
|
||||
const char * userAgent;
|
||||
/* Prefix for the User-Agent HTTP header, reflecting facilities
|
||||
outside of Xmlrpc-c. The actual User-Agent header consists
|
||||
of this prefix plus information about Xmlrpc-c. NULL means
|
||||
none.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* This is all stuff that really ought to be in a Curl object,
|
||||
but the Curl library is a little too simple for that. So we
|
||||
build a layer on top of Curl, and define this "transaction," as
|
||||
an object subordinate to a Curl "session."
|
||||
*/
|
||||
CURL * curlSessionP;
|
||||
/* Handle for the Curl session that hosts this transaction */
|
||||
char curlError[CURL_ERROR_SIZE];
|
||||
/* Error message from Curl */
|
||||
struct curl_slist * headerList;
|
||||
/* The HTTP headers for the transaction */
|
||||
const char * serverUrl; /* malloc'ed - belongs to this object */
|
||||
} curlTransaction;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct list_head link; /* link in transport's list of RPCs */
|
||||
CURL * curlSessionP;
|
||||
/* The Curl session we use for this transaction. Note that only
|
||||
one RPC at a time can use a particular Curl session, so this
|
||||
had better not be a session that some other RPC is using
|
||||
simultaneously.
|
||||
*/
|
||||
curlTransaction * curlTransactionP;
|
||||
/* The object which does the HTTP transaction, with no knowledge
|
||||
of XML-RPC or Xmlrpc-c.
|
||||
*/
|
||||
xmlrpc_mem_block * responseXmlP;
|
||||
xmlrpc_bool threadExists;
|
||||
pthread_t thread;
|
||||
xmlrpc_transport_asynch_complete complete;
|
||||
/* Routine to call to complete the RPC after it is complete HTTP-wise.
|
||||
NULL if none.
|
||||
*/
|
||||
struct xmlrpc_call_info * callInfoP;
|
||||
/* User's identifier for this RPC */
|
||||
} rpc;
|
||||
|
||||
|
||||
|
||||
static size_t
|
||||
collect(void * const ptr,
|
||||
size_t const size,
|
||||
size_t const nmemb,
|
||||
FILE * const stream) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a Curl output function. Curl calls this to deliver the
|
||||
HTTP response body. Curl thinks it's writing to a POSIX stream.
|
||||
-----------------------------------------------------------------------------*/
|
||||
xmlrpc_mem_block * const responseXmlP = (xmlrpc_mem_block *) stream;
|
||||
char * const buffer = ptr;
|
||||
size_t const length = nmemb * size;
|
||||
|
||||
size_t retval;
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
xmlrpc_mem_block_append(&env, responseXmlP, buffer, length);
|
||||
if (env.fault_occurred)
|
||||
retval = (size_t)-1;
|
||||
else
|
||||
/* Really? Shouldn't it be like fread() and return 'nmemb'? */
|
||||
retval = length;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
initWindowsStuff(xmlrpc_env * const envP) {
|
||||
|
||||
#if defined (WIN32)
|
||||
/* This is CRITICAL so that cURL-Win32 works properly! */
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
wVersionRequested = MAKEWORD(1, 1);
|
||||
|
||||
err = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (err)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Winsock startup failed. WSAStartup returned rc %d", err);
|
||||
else {
|
||||
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
|
||||
/* Tell the user that we couldn't find a useable */
|
||||
/* winsock.dll. */
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR, "Winsock reported that "
|
||||
"it does not implement the requested version 1.1.");
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
WSACleanup();
|
||||
}
|
||||
#else
|
||||
if (0)
|
||||
envP->fault_occurred = TRUE; /* Avoid unused parm warning */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
getXportParms(xmlrpc_env * const envP,
|
||||
const struct xmlrpc_curl_xportparms * const curlXportParmsP,
|
||||
size_t const parmSize,
|
||||
const char ** const networkInterfaceP,
|
||||
xmlrpc_bool * const sslVerifyPeerP,
|
||||
xmlrpc_bool * const sslVerifyHostP,
|
||||
const char ** const userAgentP) {
|
||||
|
||||
if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(user_agent))
|
||||
*userAgentP = NULL;
|
||||
else if (curlXportParmsP->user_agent == NULL)
|
||||
*userAgentP = NULL;
|
||||
else
|
||||
*userAgentP = strdup(curlXportParmsP->user_agent);
|
||||
|
||||
if (!curlXportParmsP ||
|
||||
parmSize < XMLRPC_CXPSIZE(no_ssl_verifypeer))
|
||||
*sslVerifyPeerP = TRUE;
|
||||
else
|
||||
*sslVerifyPeerP = !curlXportParmsP->no_ssl_verifypeer;
|
||||
|
||||
if (!curlXportParmsP ||
|
||||
parmSize < XMLRPC_CXPSIZE(no_ssl_verifyhost))
|
||||
*sslVerifyHostP = TRUE;
|
||||
else
|
||||
*sslVerifyHostP = !curlXportParmsP->no_ssl_verifyhost;
|
||||
|
||||
if (!curlXportParmsP || parmSize < XMLRPC_CXPSIZE(network_interface))
|
||||
*networkInterfaceP = NULL;
|
||||
else if (curlXportParmsP->network_interface == NULL)
|
||||
*networkInterfaceP = NULL;
|
||||
else {
|
||||
*networkInterfaceP = strdup(curlXportParmsP->network_interface);
|
||||
if (*networkInterfaceP == NULL)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Unable to allocate space for network interface name.");
|
||||
if (envP->fault_occurred)
|
||||
strfree(*networkInterfaceP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createSyncCurlSession(xmlrpc_env * const envP,
|
||||
CURL ** const curlSessionPP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Create a Curl session to be used for multiple serial transactions.
|
||||
The Curl session we create is not complete -- it still has to be
|
||||
further set up for each particular transaction.
|
||||
|
||||
We can't set up anything here that changes from one transaction to the
|
||||
next.
|
||||
|
||||
We don't bother setting up anything that has to be set up for an
|
||||
asynchronous transaction because code that is common between synchronous
|
||||
and asynchronous transactions takes care of that anyway.
|
||||
|
||||
That leaves things such as cookies that don't exist for asynchronous
|
||||
transactions, and are common to multiple serial synchronous
|
||||
transactions.
|
||||
-----------------------------------------------------------------------------*/
|
||||
CURL * const curlSessionP = curl_easy_init();
|
||||
|
||||
if (curlSessionP == NULL)
|
||||
xmlrpc_faultf(envP, "Could not create Curl session. "
|
||||
"curl_easy_init() failed.");
|
||||
else {
|
||||
/* The following is a trick. CURLOPT_COOKIEFILE is the name
|
||||
of the file containing the initial cookies for the Curl
|
||||
session. But setting it is also what turns on the cookie
|
||||
function itself, whereby the Curl library accepts and
|
||||
stores cookies from the server and sends them back on
|
||||
future requests. We don't have a file of initial cookies, but
|
||||
we want to turn on cookie function, so we set the option to
|
||||
something we know does not validly name a file. Curl will
|
||||
ignore the error and just start up cookie function with no
|
||||
initial cookies.
|
||||
*/
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_COOKIEFILE, "");
|
||||
|
||||
*curlSessionPP = curlSessionP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroySyncCurlSession(CURL * const curlSessionP) {
|
||||
|
||||
curl_easy_cleanup(curlSessionP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
create(xmlrpc_env * const envP,
|
||||
int const flags ATTR_UNUSED,
|
||||
const char * const appname ATTR_UNUSED,
|
||||
const char * const appversion ATTR_UNUSED,
|
||||
const struct xmlrpc_xportparms * const transportparmsP,
|
||||
size_t const parm_size,
|
||||
struct xmlrpc_client_transport ** const handlePP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This does the 'create' operation for a Curl client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
struct xmlrpc_curl_xportparms * const curlXportParmsP =
|
||||
(struct xmlrpc_curl_xportparms *) transportparmsP;
|
||||
|
||||
struct xmlrpc_client_transport * transportP;
|
||||
|
||||
initWindowsStuff(envP);
|
||||
|
||||
MALLOCVAR(transportP);
|
||||
if (transportP == NULL)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Unable to allocate transport descriptor.");
|
||||
else {
|
||||
pthread_mutex_init(&transportP->listLock, NULL);
|
||||
|
||||
list_make_empty(&transportP->rpcList);
|
||||
|
||||
/*
|
||||
* This is the main global constructor for the app. Call this before
|
||||
* _any_ libcurl usage. If this fails, *NO* libcurl functions may be
|
||||
* used, or havoc may be the result.
|
||||
*/
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
/* The above makes it look like Curl is not re-entrant. We should
|
||||
check into that.
|
||||
*/
|
||||
|
||||
getXportParms(envP, curlXportParmsP, parm_size,
|
||||
&transportP->networkInterface,
|
||||
&transportP->sslVerifyPeer,
|
||||
&transportP->sslVerifyHost,
|
||||
&transportP->userAgent);
|
||||
|
||||
if (!envP->fault_occurred) {
|
||||
pthread_mutex_init(&transportP->syncCurlSessionLock, NULL);
|
||||
createSyncCurlSession(envP, &transportP->syncCurlSessionP);
|
||||
|
||||
if (envP->fault_occurred)
|
||||
strfree(transportP->networkInterface);
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
free(transportP);
|
||||
}
|
||||
*handlePP = transportP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
termWindowStuff(void) {
|
||||
|
||||
#if defined (WIN32)
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroy(struct xmlrpc_client_transport * const clientTransportP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This does the 'destroy' operation for a Curl client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
XMLRPC_ASSERT(clientTransportP != NULL);
|
||||
|
||||
XMLRPC_ASSERT(list_is_empty(&clientTransportP->rpcList));
|
||||
|
||||
destroySyncCurlSession(clientTransportP->syncCurlSessionP);
|
||||
pthread_mutex_destroy(&clientTransportP->syncCurlSessionLock);
|
||||
|
||||
if (clientTransportP->networkInterface)
|
||||
strfree(clientTransportP->networkInterface);
|
||||
if (clientTransportP->userAgent)
|
||||
strfree(clientTransportP->userAgent);
|
||||
|
||||
/* We want to call curl_global_cleanup() now, but can't. See
|
||||
explanation of Curl global variables at the top of this file.
|
||||
*/
|
||||
|
||||
pthread_mutex_destroy(&clientTransportP->listLock);
|
||||
|
||||
termWindowStuff();
|
||||
|
||||
free(clientTransportP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
addHeader(xmlrpc_env * const envP,
|
||||
struct curl_slist ** const headerListP,
|
||||
const char * const headerText) {
|
||||
|
||||
struct curl_slist * newHeaderList;
|
||||
newHeaderList = curl_slist_append(*headerListP, headerText);
|
||||
if (newHeaderList == NULL)
|
||||
xmlrpc_faultf(envP,
|
||||
"Could not add header '%s'. "
|
||||
"curl_slist_append() failed.", headerText);
|
||||
else
|
||||
*headerListP = newHeaderList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
addContentTypeHeader(xmlrpc_env * const envP,
|
||||
struct curl_slist ** const headerListP) {
|
||||
|
||||
addHeader(envP, headerListP, "Content-Type: text/xml");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
addUserAgentHeader(xmlrpc_env * const envP,
|
||||
struct curl_slist ** const headerListP,
|
||||
const char * const userAgent) {
|
||||
|
||||
if (userAgent) {
|
||||
curl_version_info_data * const curlInfoP =
|
||||
curl_version_info(CURLVERSION_NOW);
|
||||
char curlVersion[32];
|
||||
const char * userAgentHeader;
|
||||
|
||||
snprintf(curlVersion, sizeof(curlVersion), "%u.%u.%u",
|
||||
(curlInfoP->version_num >> 16) && 0xff,
|
||||
(curlInfoP->version_num >> 8) && 0xff,
|
||||
(curlInfoP->version_num >> 0) && 0xff
|
||||
);
|
||||
|
||||
casprintf(&userAgentHeader,
|
||||
"User-Agent: %s Xmlrpc-c/%s Curl/%s",
|
||||
userAgent, XMLRPC_C_VERSION, curlVersion);
|
||||
|
||||
if (userAgentHeader == NULL)
|
||||
xmlrpc_faultf(envP, "Couldn't allocate memory for "
|
||||
"User-Agent header");
|
||||
else {
|
||||
addHeader(envP, headerListP, userAgentHeader);
|
||||
|
||||
strfree(userAgentHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
addAuthorizationHeader(xmlrpc_env * const envP,
|
||||
struct curl_slist ** const headerListP,
|
||||
const char * const basicAuthInfo) {
|
||||
|
||||
if (basicAuthInfo) {
|
||||
const char * authorizationHeader;
|
||||
|
||||
casprintf(&authorizationHeader, "Authorization: %s", basicAuthInfo);
|
||||
|
||||
if (authorizationHeader == NULL)
|
||||
xmlrpc_faultf(envP, "Couldn't allocate memory for "
|
||||
"Authorization header");
|
||||
else {
|
||||
addHeader(envP, headerListP, authorizationHeader);
|
||||
|
||||
strfree(authorizationHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createCurlHeaderList(xmlrpc_env * const envP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
const char * const userAgent,
|
||||
struct curl_slist ** const headerListP) {
|
||||
|
||||
struct curl_slist * headerList;
|
||||
|
||||
headerList = NULL; /* initial value - empty list */
|
||||
|
||||
addContentTypeHeader(envP, &headerList);
|
||||
if (!envP->fault_occurred) {
|
||||
addUserAgentHeader(envP, &headerList, userAgent);
|
||||
if (!envP->fault_occurred) {
|
||||
addAuthorizationHeader(envP, &headerList,
|
||||
serverP->_http_basic_auth);
|
||||
}
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
curl_slist_free_all(headerList);
|
||||
else
|
||||
*headerListP = headerList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
setupCurlSession(xmlrpc_env * const envP,
|
||||
curlTransaction * const curlTransactionP,
|
||||
xmlrpc_mem_block * const callXmlP,
|
||||
xmlrpc_mem_block * const responseXmlP,
|
||||
const char * const networkInterface,
|
||||
xmlrpc_bool const sslVerifyPeer,
|
||||
xmlrpc_bool const sslVerifyHost) {
|
||||
|
||||
CURL * const curlSessionP = curlTransactionP->curlSessionP;
|
||||
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_POST, 1);
|
||||
if (networkInterface)
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_INTERFACE, networkInterface);
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_URL, curlTransactionP->serverUrl);
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYPEER, sslVerifyPeer);
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_SSL_VERIFYHOST,
|
||||
sslVerifyHost ? 2 : 0);
|
||||
XMLRPC_MEMBLOCK_APPEND(char, envP, callXmlP, "\0", 1);
|
||||
if (!envP->fault_occurred) {
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_POSTFIELDS,
|
||||
XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP));
|
||||
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_FILE, responseXmlP);
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_HEADER, 0 );
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_WRITEFUNCTION, collect);
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_ERRORBUFFER,
|
||||
curlTransactionP->curlError);
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_NOPROGRESS, 1);
|
||||
|
||||
curl_easy_setopt(curlSessionP, CURLOPT_HTTPHEADER,
|
||||
curlTransactionP->headerList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createCurlTransaction(xmlrpc_env * const envP,
|
||||
CURL * const curlSessionP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
xmlrpc_mem_block * const callXmlP,
|
||||
xmlrpc_mem_block * const responseXmlP,
|
||||
const char * const networkInterface,
|
||||
xmlrpc_bool const sslVerifyPeer,
|
||||
xmlrpc_bool const sslVerifyHost,
|
||||
const char * const userAgent,
|
||||
curlTransaction ** const curlTransactionPP) {
|
||||
|
||||
curlTransaction * curlTransactionP;
|
||||
|
||||
MALLOCVAR(curlTransactionP);
|
||||
if (curlTransactionP == NULL)
|
||||
xmlrpc_faultf(envP, "No memory to create Curl transaction.");
|
||||
else {
|
||||
curlTransactionP->curlSessionP = curlSessionP;
|
||||
|
||||
curlTransactionP->serverUrl = strdup(serverP->_server_url);
|
||||
if (curlTransactionP->serverUrl == NULL)
|
||||
xmlrpc_faultf(envP, "Out of memory to store server URL.");
|
||||
else {
|
||||
createCurlHeaderList(envP, serverP, userAgent,
|
||||
&curlTransactionP->headerList);
|
||||
|
||||
if (!envP->fault_occurred)
|
||||
setupCurlSession(envP, curlTransactionP,
|
||||
callXmlP, responseXmlP,
|
||||
networkInterface,
|
||||
sslVerifyPeer, sslVerifyHost);
|
||||
|
||||
if (envP->fault_occurred)
|
||||
strfree(curlTransactionP->serverUrl);
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
free(curlTransactionP);
|
||||
}
|
||||
*curlTransactionPP = curlTransactionP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyCurlTransaction(curlTransaction * const curlTransactionP) {
|
||||
|
||||
curl_slist_free_all(curlTransactionP->headerList);
|
||||
strfree(curlTransactionP->serverUrl);
|
||||
|
||||
free(curlTransactionP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
performCurlTransaction(xmlrpc_env * const envP,
|
||||
curlTransaction * const curlTransactionP) {
|
||||
|
||||
CURL * const curlSessionP = curlTransactionP->curlSessionP;
|
||||
|
||||
CURLcode res;
|
||||
|
||||
res = curl_easy_perform(curlSessionP);
|
||||
|
||||
if (res != CURLE_OK)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_NETWORK_ERROR, "Curl failed to perform "
|
||||
"HTTP POST request. curl_easy_perform() says: %s",
|
||||
curlTransactionP->curlError);
|
||||
else {
|
||||
CURLcode res;
|
||||
long http_result;
|
||||
res = curl_easy_getinfo(curlSessionP, CURLINFO_HTTP_CODE,
|
||||
&http_result);
|
||||
|
||||
if (res != CURLE_OK)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Curl performed the HTTP POST request, but was "
|
||||
"unable to say what the HTTP result code was. "
|
||||
"curl_easy_getinfo(CURLINFO_HTTP_CODE) says: %s",
|
||||
curlTransactionP->curlError);
|
||||
else {
|
||||
if (http_result != 200)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_NETWORK_ERROR, "HTTP response: %ld",
|
||||
http_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
doAsyncRpc2(void * const arg) {
|
||||
|
||||
rpc * const rpcP = arg;
|
||||
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
performCurlTransaction(&env, rpcP->curlTransactionP);
|
||||
|
||||
rpcP->complete(rpcP->callInfoP, rpcP->responseXmlP, env);
|
||||
|
||||
xmlrpc_env_clean(&env);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
static unsigned __stdcall
|
||||
doAsyncRpc(void * arg) {
|
||||
doAsyncRpc2(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static void *
|
||||
doAsyncRpc(void * arg) {
|
||||
doAsyncRpc2(arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createThread(xmlrpc_env * const envP,
|
||||
void * (*threadRoutine)(void *),
|
||||
rpc * const rpcP,
|
||||
pthread_t * const threadP) {
|
||||
|
||||
int rc;
|
||||
|
||||
rc = pthread_create(threadP, NULL, threadRoutine, rpcP);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
break;
|
||||
case EAGAIN:
|
||||
xmlrpc_faultf(envP, "pthread_create() failed. "
|
||||
"System resources exceeded.");
|
||||
break;
|
||||
case EINVAL:
|
||||
xmlrpc_faultf(envP, "pthread_create() failed. "
|
||||
"Parameter error");
|
||||
break;
|
||||
case ENOMEM:
|
||||
xmlrpc_faultf(envP, "pthread_create() failed. "
|
||||
"No memory for new thread.");
|
||||
break;
|
||||
default:
|
||||
xmlrpc_faultf(envP, "pthread_create() failed. "
|
||||
"Unrecognized error code %d.", rc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createRpc(xmlrpc_env * const envP,
|
||||
struct xmlrpc_client_transport * const clientTransportP,
|
||||
CURL * const curlSessionP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
xmlrpc_mem_block * const callXmlP,
|
||||
xmlrpc_mem_block * const responseXmlP,
|
||||
xmlrpc_transport_asynch_complete complete,
|
||||
struct xmlrpc_call_info * const callInfoP,
|
||||
rpc ** const rpcPP) {
|
||||
|
||||
rpc * rpcP;
|
||||
|
||||
MALLOCVAR(rpcP);
|
||||
if (rpcP == NULL)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Couldn't allocate memory for rpc object");
|
||||
else {
|
||||
rpcP->callInfoP = callInfoP;
|
||||
rpcP->complete = complete;
|
||||
rpcP->responseXmlP = responseXmlP;
|
||||
rpcP->threadExists = FALSE;
|
||||
|
||||
rpcP->curlSessionP = curlSessionP;
|
||||
createCurlTransaction(envP,
|
||||
curlSessionP,
|
||||
serverP,
|
||||
callXmlP, responseXmlP,
|
||||
clientTransportP->networkInterface,
|
||||
clientTransportP->sslVerifyPeer,
|
||||
clientTransportP->sslVerifyHost,
|
||||
clientTransportP->userAgent,
|
||||
&rpcP->curlTransactionP);
|
||||
if (!envP->fault_occurred) {
|
||||
list_init_header(&rpcP->link, rpcP);
|
||||
pthread_mutex_lock(&clientTransportP->listLock);
|
||||
list_add_head(&clientTransportP->rpcList, &rpcP->link);
|
||||
pthread_mutex_unlock(&clientTransportP->listLock);
|
||||
|
||||
if (envP->fault_occurred)
|
||||
destroyCurlTransaction(rpcP->curlTransactionP);
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
free(rpcP);
|
||||
}
|
||||
*rpcPP = rpcP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyRpc(rpc * const rpcP) {
|
||||
|
||||
XMLRPC_ASSERT_PTR_OK(rpcP);
|
||||
XMLRPC_ASSERT(!rpcP->threadExists);
|
||||
|
||||
destroyCurlTransaction(rpcP->curlTransactionP);
|
||||
|
||||
list_remove(&rpcP->link);
|
||||
|
||||
free(rpcP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
performRpc(xmlrpc_env * const envP,
|
||||
rpc * const rpcP) {
|
||||
|
||||
performCurlTransaction(envP, rpcP->curlTransactionP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
startRpc(xmlrpc_env * const envP,
|
||||
rpc * const rpcP) {
|
||||
|
||||
createThread(envP, &doAsyncRpc, rpcP, &rpcP->thread);
|
||||
if (!envP->fault_occurred)
|
||||
rpcP->threadExists = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
sendRequest(xmlrpc_env * const envP,
|
||||
struct xmlrpc_client_transport * const clientTransportP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
xmlrpc_mem_block * const callXmlP,
|
||||
xmlrpc_transport_asynch_complete complete,
|
||||
struct xmlrpc_call_info * const callInfoP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Initiate an XML-RPC rpc asynchronously. Don't wait for it to go to
|
||||
the server.
|
||||
|
||||
Unless we return failure, we arrange to have complete() called when
|
||||
the rpc completes.
|
||||
|
||||
This does the 'send_request' operation for a Curl client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpc * rpcP;
|
||||
xmlrpc_mem_block * responseXmlP;
|
||||
|
||||
responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
|
||||
if (!envP->fault_occurred) {
|
||||
CURL * const curlSessionP = curl_easy_init();
|
||||
|
||||
if (curlSessionP == NULL)
|
||||
xmlrpc_faultf(envP, "Could not create Curl session. "
|
||||
"curl_easy_init() failed.");
|
||||
else {
|
||||
createRpc(envP, clientTransportP, curlSessionP, serverP,
|
||||
callXmlP, responseXmlP,
|
||||
complete, callInfoP,
|
||||
&rpcP);
|
||||
|
||||
if (!envP->fault_occurred) {
|
||||
startRpc(envP, rpcP);
|
||||
|
||||
if (envP->fault_occurred)
|
||||
destroyRpc(rpcP);
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
curl_easy_cleanup(curlSessionP);
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
|
||||
}
|
||||
/* The user's eventual finish_asynch call will destroy this RPC,
|
||||
Curl session, and response buffer
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
finishRpc(struct list_head * const headerP,
|
||||
void * const context ATTR_UNUSED) {
|
||||
|
||||
rpc * const rpcP = headerP->itemP;
|
||||
|
||||
if (rpcP->threadExists) {
|
||||
void *status;
|
||||
int result;
|
||||
|
||||
result = pthread_join(rpcP->thread, &status);
|
||||
|
||||
rpcP->threadExists = FALSE;
|
||||
}
|
||||
|
||||
XMLRPC_MEMBLOCK_FREE(char, rpcP->responseXmlP);
|
||||
|
||||
curl_easy_cleanup(rpcP->curlSessionP);
|
||||
|
||||
destroyRpc(rpcP);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
finishAsynch(
|
||||
struct xmlrpc_client_transport * const clientTransportP ATTR_UNUSED,
|
||||
xmlrpc_timeoutType const timeoutType ATTR_UNUSED,
|
||||
xmlrpc_timeout const timeout ATTR_UNUSED) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Wait for the threads of all outstanding RPCs to exit and destroy those
|
||||
RPCs.
|
||||
|
||||
This does the 'finish_asynch' operation for a Curl client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
/* We ignore any timeout request. Some day, we should figure out how
|
||||
to set an alarm and interrupt running threads.
|
||||
*/
|
||||
|
||||
pthread_mutex_lock(&clientTransportP->listLock);
|
||||
|
||||
list_foreach(&clientTransportP->rpcList, finishRpc, NULL);
|
||||
|
||||
pthread_mutex_unlock(&clientTransportP->listLock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
call(xmlrpc_env * const envP,
|
||||
struct xmlrpc_client_transport * const clientTransportP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
xmlrpc_mem_block * const callXmlP,
|
||||
xmlrpc_mem_block ** const responsePP) {
|
||||
|
||||
xmlrpc_mem_block * responseXmlP;
|
||||
rpc * rpcP;
|
||||
|
||||
XMLRPC_ASSERT_ENV_OK(envP);
|
||||
XMLRPC_ASSERT_PTR_OK(serverP);
|
||||
XMLRPC_ASSERT_PTR_OK(callXmlP);
|
||||
XMLRPC_ASSERT_PTR_OK(responsePP);
|
||||
|
||||
responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
|
||||
if (!envP->fault_occurred) {
|
||||
pthread_mutex_lock(&clientTransportP->syncCurlSessionLock);
|
||||
createRpc(envP, clientTransportP, clientTransportP->syncCurlSessionP,
|
||||
serverP,
|
||||
callXmlP, responseXmlP,
|
||||
NULL, NULL,
|
||||
&rpcP);
|
||||
|
||||
if (!envP->fault_occurred) {
|
||||
performRpc(envP, rpcP);
|
||||
|
||||
*responsePP = responseXmlP;
|
||||
|
||||
destroyRpc(rpcP);
|
||||
}
|
||||
pthread_mutex_unlock(&clientTransportP->syncCurlSessionLock);
|
||||
if (envP->fault_occurred)
|
||||
XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops = {
|
||||
&create,
|
||||
&destroy,
|
||||
&sendRequest,
|
||||
&call,
|
||||
&finishAsynch,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef XMLRPC_CURL_TRANSPORT_H
|
||||
#define XMLRPC_CURL_TRANSPORT_H
|
||||
|
||||
#include "xmlrpc-c/transport.h"
|
||||
|
||||
extern struct xmlrpc_client_transport_ops xmlrpc_curl_transport_ops;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,314 @@
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ../..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
ABYSS_SUBDIR = @ABYSS_SUBDIR@
|
||||
AS = @AS@
|
||||
ASYNCH_CLIENT = @ASYNCH_CLIENT@
|
||||
AUTH_CLIENT = @AUTH_CLIENT@
|
||||
AVAILABLE_MODULES = @AVAILABLE_MODULES@
|
||||
CC = @CC@
|
||||
CC_WARN_FLAGS = @CC_WARN_FLAGS@
|
||||
CLIENTTEST = @CLIENTTEST@
|
||||
CONFIGURE_DATE = @CONFIGURE_DATE@
|
||||
CPPTEST = @CPPTEST@
|
||||
CPP_WARN_FLAGS = @CPP_WARN_FLAGS@
|
||||
CXX = @CXX@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
EFRPCTEST = @EFRPCTEST@
|
||||
EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@
|
||||
INTEROP_CGI = @INTEROP_CGI@
|
||||
INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBWWW_CFLAGS = @LIBWWW_CFLAGS@
|
||||
LIBWWW_CONFIG = @LIBWWW_CONFIG@
|
||||
LIBWWW_LDADD = @LIBWWW_LDADD@
|
||||
LIBWWW_LIBDIR = @LIBWWW_LIBDIR@
|
||||
LIBWWW_RPATH = @LIBWWW_RPATH@
|
||||
LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@
|
||||
LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@
|
||||
LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@
|
||||
LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@
|
||||
LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@
|
||||
LN_S = @LN_S@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MEERKAT_APP_LIST = @MEERKAT_APP_LIST@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
PACKAGE = @PACKAGE@
|
||||
QUERY_MEERKAT = @QUERY_MEERKAT@
|
||||
RANLIB = @RANLIB@
|
||||
SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@
|
||||
SERVER = @SERVER@
|
||||
SERVERTEST = @SERVERTEST@
|
||||
SYNCH_CLIENT = @SYNCH_CLIENT@
|
||||
VALIDATEE = @VALIDATEE@
|
||||
VERSION = @VERSION@
|
||||
VERSION_INFO = @VERSION_INFO@
|
||||
XMLRPCCPP_H = @XMLRPCCPP_H@
|
||||
XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@
|
||||
XMLRPC_CGI_H = @XMLRPC_CGI_H@
|
||||
XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@
|
||||
XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@
|
||||
|
||||
SUBDIRS = gennmtab xmltok xmlparse xmlwf sample
|
||||
EXTRA_DIST = expat.html expat.dsw
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../../xmlrpc_config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_COMMON = Makefile.in
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
all-recursive install-data-recursive install-exec-recursive \
|
||||
installdirs-recursive install-recursive uninstall-recursive \
|
||||
check-recursive installcheck-recursive info-recursive dvi-recursive:
|
||||
@set fnord $(MAKEFLAGS); amf=$$2; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
mostlyclean-recursive clean-recursive distclean-recursive \
|
||||
maintainer-clean-recursive:
|
||||
@set fnord $(MAKEFLAGS); amf=$$2; \
|
||||
dot_seen=no; \
|
||||
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
rev="$$subdir $$rev"; \
|
||||
test "$$subdir" = "." && dot_seen=yes; \
|
||||
done; \
|
||||
test "$$dot_seen" = "no" && rev=". $$rev"; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $$unique $(LISP)
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = lib/expat
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
for subdir in $(SUBDIRS); do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d $(distdir)/$$subdir \
|
||||
|| mkdir $(distdir)/$$subdir \
|
||||
|| exit 1; \
|
||||
chmod 777 $(distdir)/$$subdir; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-recursive
|
||||
dvi-am:
|
||||
dvi: dvi-recursive
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
installcheck-am:
|
||||
installcheck: installcheck-recursive
|
||||
install-exec-am:
|
||||
install-exec: install-exec-recursive
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-recursive
|
||||
uninstall-am:
|
||||
uninstall: uninstall-recursive
|
||||
all-am: Makefile
|
||||
all-redirect: all-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-tags mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
clean-am: clean-tags clean-generic mostlyclean-am
|
||||
|
||||
clean: clean-recursive
|
||||
|
||||
distclean-am: distclean-tags distclean-generic clean-am
|
||||
-rm -f libtool
|
||||
|
||||
distclean: distclean-recursive
|
||||
|
||||
maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
|
||||
distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
|
||||
.PHONY: install-data-recursive uninstall-data-recursive \
|
||||
install-exec-recursive uninstall-exec-recursive installdirs-recursive \
|
||||
uninstalldirs-recursive all-recursive check-recursive \
|
||||
installcheck-recursive info-recursive dvi-recursive \
|
||||
mostlyclean-recursive distclean-recursive clean-recursive \
|
||||
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
|
||||
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
|
||||
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
|
||||
install-exec install-data-am install-data install-am install \
|
||||
uninstall-am uninstall all-redirect all-am all installdirs-am \
|
||||
installdirs mostlyclean-generic distclean-generic clean-generic \
|
||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
|
||||
dep:
|
||||
@@ -0,0 +1,74 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "gennmtab"=.\gennmtab\gennmtab.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "xmlparse"=.\xmlparse\xmlparse.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name xmltok
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "xmltok"=.\xmltok\xmltok.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name gennmtab
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "xmlwf"=.\xmlwf\xmlwf.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name xmlparse
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
|
||||
<HTML>
|
||||
|
||||
<TITLE>expat</TITLE>
|
||||
|
||||
<BODY>
|
||||
|
||||
<H1>expat - XML Parser Toolkit</H1>
|
||||
|
||||
<H3>Version 1.2</H3>
|
||||
|
||||
<P>Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center
|
||||
Ltd. Expat is freely available with source under a very liberal <a
|
||||
href="copying.txt">license</a> (the MIT license).</P>
|
||||
|
||||
<P>This is a production version of expat. Relative to expat 1.1, it
|
||||
adds support for parsing external DTDs and parameter entities.
|
||||
Compiling with -DXML_DTD enables this support. There's a new
|
||||
<CODE>-p</CODE> option for xmlwf which will cause it to process
|
||||
external DTDs and parameter entities; this implies the <CODE>-x</CODE>
|
||||
option. See the comment above <CODE>XML_SetParamEntityParsing</CODE>
|
||||
in <CODE>xmlparse.h</CODE> for the API addition that enables this.</P>
|
||||
|
||||
<P>Expat is an <A
|
||||
HREF="http://www.w3.org/TR/1998/REC-xml-19980210">XML 1.0</A> parser
|
||||
written in C. It aims to be fully conforming. It is currently not a
|
||||
validating XML processor. The current production version of expat 1.X
|
||||
can be downloaded from <A href =
|
||||
"ftp://ftp.jclark.com/pub/xml/expat.zip"
|
||||
>ftp://ftp.jclark.com/pub/xml/expat.zip</A>.</P>
|
||||
|
||||
<P>Development of expat 2.0 is being handled by a team led by Clark
|
||||
Cooper, hosted by <A
|
||||
href="http://www.sourceforge.net">sourceforge.net</A>. See <A href=
|
||||
"http://expat.sourceforge.net">http://expat.sourceforge.net</A> for
|
||||
the latest on expat 2.0.</P>
|
||||
|
||||
<P>The directory <SAMP>xmltok</SAMP> contains a low-level library for
|
||||
tokenizing XML. The interface is documented in
|
||||
<SAMP>xmltok/xmltok.h</SAMP>.</P>
|
||||
|
||||
<P>The directory <SAMP>xmlparse</SAMP> contains an XML parser library
|
||||
which is built on top of the <SAMP>xmltok</SAMP> library. The
|
||||
interface is documented in <SAMP>xmlparse/xmlparse.h</SAMP>. The
|
||||
directory <SAMP>sample</SAMP> contains a simple example program using
|
||||
this interface; <SAMP>sample/build.bat</SAMP> is a batch file to build
|
||||
the example using Visual C++.</P>
|
||||
|
||||
<P>The directory <SAMP>xmlwf</SAMP> contains the <SAMP>xmlwf</SAMP>
|
||||
application, which uses the <SAMP>xmlparse</SAMP> library. The
|
||||
arguments to <SAMP>xmlwf</SAMP> are one or more files which are each
|
||||
to be checked for well-formedness. An option <SAMP>-d
|
||||
<VAR>dir</VAR></SAMP> can be specified; for each well-formed input
|
||||
file the corresponding <A
|
||||
href="http://www.jclark.com/xml/canonxml.html">canonical XML</A> will
|
||||
be written to <SAMP>dir/<VAR>f</VAR></SAMP>, where
|
||||
<SAMP><VAR>f</VAR></SAMP> is the filename (without any path) of the
|
||||
input file. A <CODE>-x</CODE> option will cause references to
|
||||
external general entities to be processed. A <CODE>-s</CODE> option
|
||||
will make documents that are not standalone cause an error (a document
|
||||
is considered standalone if either it is intrinsically standalone
|
||||
because it has no external subset and no references to parameter
|
||||
entities in the internal subset or it is declared as standalone in the
|
||||
XML declaration).</P>
|
||||
|
||||
<P>The <SAMP>bin</SAMP> directory contains Win32 executables. The
|
||||
<SAMP>lib</SAMP> directory contains Win32 import libraries.</P>
|
||||
|
||||
<P>Answers to some frequently asked questions about expat can be found
|
||||
in the <A
|
||||
HREF="http://www.jclark.com/xml/expatfaq.html">expat
|
||||
FAQ</A>.</P>
|
||||
|
||||
<P></P>
|
||||
|
||||
<ADDRESS>
|
||||
|
||||
<A HREF="mailto:jjc@jclark.com">James Clark</A>
|
||||
|
||||
</ADDRESS>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
@@ -0,0 +1 @@
|
||||
gennmtab
|
||||
@@ -0,0 +1,45 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../../..
|
||||
endif
|
||||
|
||||
include $(SRCDIR)/Makefile.config
|
||||
|
||||
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
|
||||
|
||||
LDFLAGS = $(LADD)
|
||||
|
||||
INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/lib/util/include
|
||||
|
||||
default: all
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
.PHONY: all
|
||||
all: gennmtab
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-common
|
||||
rm -f gennmtab
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean distclean-common
|
||||
|
||||
.PHONY: tags
|
||||
tags: TAGS
|
||||
|
||||
.PHONY: distdir
|
||||
distdir:
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
|
||||
.PHONY: dep
|
||||
dep: dep-common
|
||||
|
||||
gennmtab.o:%.o:%.c
|
||||
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES)
|
||||
|
||||
gennmtab:%:%.o
|
||||
$(LINK) -o $@ $(LDFLAGS) $^
|
||||
|
||||
include Makefile.depend
|
||||
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "xmlrpc_config.h"
|
||||
|
||||
struct range {
|
||||
int start;
|
||||
int end;
|
||||
};
|
||||
|
||||
struct range nmstrt[] = {
|
||||
{ '_', 0 },
|
||||
{ ':', 0 },
|
||||
/* 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, 0 },
|
||||
{ 0x0388, 0x038a },
|
||||
{ 0x038c, 0 },
|
||||
{ 0x038e, 0x03a1 },
|
||||
{ 0x03a3, 0x03ce },
|
||||
{ 0x03d0, 0x03d6 },
|
||||
{ 0x03da, 0 },
|
||||
{ 0x03dc, 0 },
|
||||
{ 0x03de, 0 },
|
||||
{ 0x03e0, 0 },
|
||||
{ 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, 0 },
|
||||
{ 0x0561, 0x0586 },
|
||||
{ 0x05d0, 0x05ea },
|
||||
{ 0x05f0, 0x05f2 },
|
||||
{ 0x0621, 0x063a },
|
||||
{ 0x0641, 0x064a },
|
||||
{ 0x0671, 0x06b7 },
|
||||
{ 0x06ba, 0x06be },
|
||||
{ 0x06c0, 0x06ce },
|
||||
{ 0x06d0, 0x06d3 },
|
||||
{ 0x06d5, 0 },
|
||||
{ 0x06e5, 0x06e6 },
|
||||
{ 0x0905, 0x0939 },
|
||||
{ 0x093d, 0 },
|
||||
{ 0x0958, 0x0961 },
|
||||
{ 0x0985, 0x098c },
|
||||
{ 0x098f, 0x0990 },
|
||||
{ 0x0993, 0x09a8 },
|
||||
{ 0x09aa, 0x09b0 },
|
||||
{ 0x09b2, 0 },
|
||||
{ 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, 0 },
|
||||
{ 0x0a72, 0x0a74 },
|
||||
{ 0x0a85, 0x0a8b },
|
||||
{ 0x0a8d, 0 },
|
||||
{ 0x0a8f, 0x0a91 },
|
||||
{ 0x0a93, 0x0aa8 },
|
||||
{ 0x0aaa, 0x0ab0 },
|
||||
{ 0x0ab2, 0x0ab3 },
|
||||
{ 0x0ab5, 0x0ab9 },
|
||||
{ 0x0abd, 0 },
|
||||
{ 0x0ae0, 0 },
|
||||
{ 0x0b05, 0x0b0c },
|
||||
{ 0x0b0f, 0x0b10 },
|
||||
{ 0x0b13, 0x0b28 },
|
||||
{ 0x0b2a, 0x0b30 },
|
||||
{ 0x0b32, 0x0b33 },
|
||||
{ 0x0b36, 0x0b39 },
|
||||
{ 0x0b3d, 0 },
|
||||
{ 0x0b5c, 0x0b5d },
|
||||
{ 0x0b5f, 0x0b61 },
|
||||
{ 0x0b85, 0x0b8a },
|
||||
{ 0x0b8e, 0x0b90 },
|
||||
{ 0x0b92, 0x0b95 },
|
||||
{ 0x0b99, 0x0b9a },
|
||||
{ 0x0b9c, 0 },
|
||||
{ 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, 0 },
|
||||
{ 0x0ce0, 0x0ce1 },
|
||||
{ 0x0d05, 0x0d0c },
|
||||
{ 0x0d0e, 0x0d10 },
|
||||
{ 0x0d12, 0x0d28 },
|
||||
{ 0x0d2a, 0x0d39 },
|
||||
{ 0x0d60, 0x0d61 },
|
||||
{ 0x0e01, 0x0e2e },
|
||||
{ 0x0e30, 0 },
|
||||
{ 0x0e32, 0x0e33 },
|
||||
{ 0x0e40, 0x0e45 },
|
||||
{ 0x0e81, 0x0e82 },
|
||||
{ 0x0e84, 0 },
|
||||
{ 0x0e87, 0x0e88 },
|
||||
{ 0x0e8a, 0 },
|
||||
{ 0x0e8d, 0 },
|
||||
{ 0x0e94, 0x0e97 },
|
||||
{ 0x0e99, 0x0e9f },
|
||||
{ 0x0ea1, 0x0ea3 },
|
||||
{ 0x0ea5, 0 },
|
||||
{ 0x0ea7, 0 },
|
||||
{ 0x0eaa, 0x0eab },
|
||||
{ 0x0ead, 0x0eae },
|
||||
{ 0x0eb0, 0 },
|
||||
{ 0x0eb2, 0x0eb3 },
|
||||
{ 0x0ebd, 0 },
|
||||
{ 0x0ec0, 0x0ec4 },
|
||||
{ 0x0f40, 0x0f47 },
|
||||
{ 0x0f49, 0x0f69 },
|
||||
{ 0x10a0, 0x10c5 },
|
||||
{ 0x10d0, 0x10f6 },
|
||||
{ 0x1100, 0 },
|
||||
{ 0x1102, 0x1103 },
|
||||
{ 0x1105, 0x1107 },
|
||||
{ 0x1109, 0 },
|
||||
{ 0x110b, 0x110c },
|
||||
{ 0x110e, 0x1112 },
|
||||
{ 0x113c, 0 },
|
||||
{ 0x113e, 0 },
|
||||
{ 0x1140, 0 },
|
||||
{ 0x114c, 0 },
|
||||
{ 0x114e, 0 },
|
||||
{ 0x1150, 0 },
|
||||
{ 0x1154, 0x1155 },
|
||||
{ 0x1159, 0 },
|
||||
{ 0x115f, 0x1161 },
|
||||
{ 0x1163, 0 },
|
||||
{ 0x1165, 0 },
|
||||
{ 0x1167, 0 },
|
||||
{ 0x1169, 0 },
|
||||
{ 0x116d, 0x116e },
|
||||
{ 0x1172, 0x1173 },
|
||||
{ 0x1175, 0 },
|
||||
{ 0x119e, 0 },
|
||||
{ 0x11a8, 0 },
|
||||
{ 0x11ab, 0 },
|
||||
{ 0x11ae, 0x11af },
|
||||
{ 0x11b7, 0x11b8 },
|
||||
{ 0x11ba, 0 },
|
||||
{ 0x11bc, 0x11c2 },
|
||||
{ 0x11eb, 0 },
|
||||
{ 0x11f0, 0 },
|
||||
{ 0x11f9, 0 },
|
||||
{ 0x1e00, 0x1e9b },
|
||||
{ 0x1ea0, 0x1ef9 },
|
||||
{ 0x1f00, 0x1f15 },
|
||||
{ 0x1f18, 0x1f1d },
|
||||
{ 0x1f20, 0x1f45 },
|
||||
{ 0x1f48, 0x1f4d },
|
||||
{ 0x1f50, 0x1f57 },
|
||||
{ 0x1f59, 0 },
|
||||
{ 0x1f5b, 0 },
|
||||
{ 0x1f5d, 0 },
|
||||
{ 0x1f5f, 0x1f7d },
|
||||
{ 0x1f80, 0x1fb4 },
|
||||
{ 0x1fb6, 0x1fbc },
|
||||
{ 0x1fbe, 0 },
|
||||
{ 0x1fc2, 0x1fc4 },
|
||||
{ 0x1fc6, 0x1fcc },
|
||||
{ 0x1fd0, 0x1fd3 },
|
||||
{ 0x1fd6, 0x1fdb },
|
||||
{ 0x1fe0, 0x1fec },
|
||||
{ 0x1ff2, 0x1ff4 },
|
||||
{ 0x1ff6, 0x1ffc },
|
||||
{ 0x2126, 0 },
|
||||
{ 0x212a, 0x212b },
|
||||
{ 0x212e, 0 },
|
||||
{ 0x2180, 0x2182 },
|
||||
{ 0x3041, 0x3094 },
|
||||
{ 0x30a1, 0x30fa },
|
||||
{ 0x3105, 0x312c },
|
||||
{ 0xac00, 0xd7a3 },
|
||||
/* Ideographic */
|
||||
{ 0x4e00, 0x9fa5 },
|
||||
{ 0x3007, 0 },
|
||||
{ 0x3021, 0x3029 },
|
||||
};
|
||||
|
||||
/* name chars that are not name start chars */
|
||||
struct range name[] = {
|
||||
{ '.', 0 },
|
||||
{ '-', 0 },
|
||||
/* CombiningChar */
|
||||
{ 0x0300, 0x0345 },
|
||||
{ 0x0360, 0x0361 },
|
||||
{ 0x0483, 0x0486 },
|
||||
{ 0x0591, 0x05a1 },
|
||||
{ 0x05a3, 0x05b9 },
|
||||
{ 0x05bb, 0x05bd },
|
||||
{ 0x05bf, 0 },
|
||||
{ 0x05c1, 0x05c2 },
|
||||
{ 0x05c4, 0 },
|
||||
{ 0x064b, 0x0652 },
|
||||
{ 0x0670, 0 },
|
||||
{ 0x06d6, 0x06dc },
|
||||
{ 0x06dd, 0x06df },
|
||||
{ 0x06e0, 0x06e4 },
|
||||
{ 0x06e7, 0x06e8 },
|
||||
{ 0x06ea, 0x06ed },
|
||||
{ 0x0901, 0x0903 },
|
||||
{ 0x093c, 0 },
|
||||
{ 0x093e, 0x094c },
|
||||
{ 0x094d, 0 },
|
||||
{ 0x0951, 0x0954 },
|
||||
{ 0x0962, 0x0963 },
|
||||
{ 0x0981, 0x0983 },
|
||||
{ 0x09bc, 0 },
|
||||
{ 0x09be, 0 },
|
||||
{ 0x09bf, 0 },
|
||||
{ 0x09c0, 0x09c4 },
|
||||
{ 0x09c7, 0x09c8 },
|
||||
{ 0x09cb, 0x09cd },
|
||||
{ 0x09d7, 0 },
|
||||
{ 0x09e2, 0x09e3 },
|
||||
{ 0x0a02, 0 },
|
||||
{ 0x0a3c, 0 },
|
||||
{ 0x0a3e, 0 },
|
||||
{ 0x0a3f, 0 },
|
||||
{ 0x0a40, 0x0a42 },
|
||||
{ 0x0a47, 0x0a48 },
|
||||
{ 0x0a4b, 0x0a4d },
|
||||
{ 0x0a70, 0x0a71 },
|
||||
{ 0x0a81, 0x0a83 },
|
||||
{ 0x0abc, 0 },
|
||||
{ 0x0abe, 0x0ac5 },
|
||||
{ 0x0ac7, 0x0ac9 },
|
||||
{ 0x0acb, 0x0acd },
|
||||
{ 0x0b01, 0x0b03 },
|
||||
{ 0x0b3c, 0 },
|
||||
{ 0x0b3e, 0x0b43 },
|
||||
{ 0x0b47, 0x0b48 },
|
||||
{ 0x0b4b, 0x0b4d },
|
||||
{ 0x0b56, 0x0b57 },
|
||||
{ 0x0b82, 0x0b83 },
|
||||
{ 0x0bbe, 0x0bc2 },
|
||||
{ 0x0bc6, 0x0bc8 },
|
||||
{ 0x0bca, 0x0bcd },
|
||||
{ 0x0bd7, 0 },
|
||||
{ 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, 0 },
|
||||
{ 0x0e31, 0 },
|
||||
{ 0x0e34, 0x0e3a },
|
||||
{ 0x0e47, 0x0e4e },
|
||||
{ 0x0eb1, 0 },
|
||||
{ 0x0eb4, 0x0eb9 },
|
||||
{ 0x0ebb, 0x0ebc },
|
||||
{ 0x0ec8, 0x0ecd },
|
||||
{ 0x0f18, 0x0f19 },
|
||||
{ 0x0f35, 0 },
|
||||
{ 0x0f37, 0 },
|
||||
{ 0x0f39, 0 },
|
||||
{ 0x0f3e, 0 },
|
||||
{ 0x0f3f, 0 },
|
||||
{ 0x0f71, 0x0f84 },
|
||||
{ 0x0f86, 0x0f8b },
|
||||
{ 0x0f90, 0x0f95 },
|
||||
{ 0x0f97, 0 },
|
||||
{ 0x0f99, 0x0fad },
|
||||
{ 0x0fb1, 0x0fb7 },
|
||||
{ 0x0fb9, 0 },
|
||||
{ 0x20d0, 0x20dc },
|
||||
{ 0x20e1, 0 },
|
||||
{ 0x302a, 0x302f },
|
||||
{ 0x3099, 0 },
|
||||
{ 0x309a, 0 },
|
||||
/* 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 , 0 },
|
||||
{ 0x02d0, 0 },
|
||||
{ 0x02d1, 0 },
|
||||
{ 0x0387, 0 },
|
||||
{ 0x0640, 0 },
|
||||
{ 0x0e46, 0 },
|
||||
{ 0x0ec6, 0 },
|
||||
{ 0x3005, 0 },
|
||||
{ 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(int const argc ATTR_UNUSED,
|
||||
char ** const argv ATTR_UNUSED) {
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
# Microsoft Developer Studio Project File - Name="gennmtab" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=gennmtab - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "gennmtab.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "gennmtab.mak" CFG="gennmtab - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "gennmtab - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "gennmtab - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "gennmtab"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "gennmtab - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release\gennmtab"
|
||||
# PROP Intermediate_Dir "Release\gennmtab"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\..\..\Bin\gennmtab.exe"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Cmds=..\..\..\Bin\gennmtab.exe >..\xmltok\nametab.h
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "gennmtab - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\Debug"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug\gennmtab"
|
||||
# PROP Intermediate_Dir "Debug\gennmtab"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x809 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\Bin\gennmtabD.exe"
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Cmds=..\..\..\Bin\gennmtabD.exe >..\xmltok\nametab.h
|
||||
# End Special Build Tool
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "gennmtab - Win32 Release"
|
||||
# Name "gennmtab - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gennmtab.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,208 @@
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ../../..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
ABYSS_SUBDIR = @ABYSS_SUBDIR@
|
||||
AS = @AS@
|
||||
ASYNCH_CLIENT = @ASYNCH_CLIENT@
|
||||
AUTH_CLIENT = @AUTH_CLIENT@
|
||||
AVAILABLE_MODULES = @AVAILABLE_MODULES@
|
||||
CC = @CC@
|
||||
CC_WARN_FLAGS = @CC_WARN_FLAGS@
|
||||
CLIENTTEST = @CLIENTTEST@
|
||||
CONFIGURE_DATE = @CONFIGURE_DATE@
|
||||
CPPTEST = @CPPTEST@
|
||||
CPP_WARN_FLAGS = @CPP_WARN_FLAGS@
|
||||
CXX = @CXX@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
EFRPCTEST = @EFRPCTEST@
|
||||
EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@
|
||||
INTEROP_CGI = @INTEROP_CGI@
|
||||
INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBWWW_CFLAGS = @LIBWWW_CFLAGS@
|
||||
LIBWWW_CONFIG = @LIBWWW_CONFIG@
|
||||
LIBWWW_LDADD = @LIBWWW_LDADD@
|
||||
LIBWWW_LIBDIR = @LIBWWW_LIBDIR@
|
||||
LIBWWW_RPATH = @LIBWWW_RPATH@
|
||||
LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@
|
||||
LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@
|
||||
LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@
|
||||
LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@
|
||||
LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@
|
||||
LN_S = @LN_S@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MEERKAT_APP_LIST = @MEERKAT_APP_LIST@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
PACKAGE = @PACKAGE@
|
||||
QUERY_MEERKAT = @QUERY_MEERKAT@
|
||||
RANLIB = @RANLIB@
|
||||
SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@
|
||||
SERVER = @SERVER@
|
||||
SERVERTEST = @SERVERTEST@
|
||||
SYNCH_CLIENT = @SYNCH_CLIENT@
|
||||
VALIDATEE = @VALIDATEE@
|
||||
VERSION = @VERSION@
|
||||
VERSION_INFO = @VERSION_INFO@
|
||||
XMLRPCCPP_H = @XMLRPCCPP_H@
|
||||
XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@
|
||||
XMLRPC_CGI_H = @XMLRPC_CGI_H@
|
||||
XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@
|
||||
XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@
|
||||
|
||||
EXTRA_DIST = build.bat elements.c
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../../../xmlrpc_config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_COMMON = Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
tags: TAGS
|
||||
TAGS:
|
||||
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = lib/expat/sample
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-exec-am:
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am:
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile
|
||||
all-redirect: all-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
clean: clean-am
|
||||
|
||||
distclean-am: distclean-generic clean-am
|
||||
-rm -f libtool
|
||||
|
||||
distclean: distclean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-generic distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
|
||||
installcheck-am installcheck install-exec-am install-exec \
|
||||
install-data-am install-data install-am install uninstall-am uninstall \
|
||||
all-redirect all-am all installdirs mostlyclean-generic \
|
||||
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||
mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
set LIB=..\xmlparse\Release;..\lib;%LIB%
|
||||
cl /nologo /DXMLTOKAPI=__declspec(dllimport) /DXMLPARSEAPI=__declspec(dllimport) /I..\xmlparse /Fe..\bin\elements elements.c xmlparse.lib
|
||||
@echo Run it using: ..\bin\elements ^<..\expat.html
|
||||
@@ -0,0 +1,46 @@
|
||||
/* This is simple demonstration of how to use expat. This program
|
||||
reads an XML document from standard input and writes a line with the
|
||||
name of each element to standard output indenting child elements by
|
||||
one tab stop more than their parent element. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "xmlparse.h"
|
||||
|
||||
void startElement(void *userData, const char *name, const char **atts)
|
||||
{
|
||||
int i;
|
||||
int *depthPtr = userData;
|
||||
for (i = 0; i < *depthPtr; i++)
|
||||
putchar('\t');
|
||||
puts(name);
|
||||
*depthPtr += 1;
|
||||
}
|
||||
|
||||
void endElement(void *userData, const char *name)
|
||||
{
|
||||
int *depthPtr = userData;
|
||||
*depthPtr -= 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
int done;
|
||||
int depth = 0;
|
||||
XML_SetUserData(parser, &depth);
|
||||
XML_SetElementHandler(parser, startElement, endElement);
|
||||
do {
|
||||
size_t len = fread(buf, 1, sizeof(buf), stdin);
|
||||
done = len < sizeof(buf);
|
||||
if (!XML_Parse(parser, buf, len, done)) {
|
||||
fprintf(stderr,
|
||||
"%s at line %d\n",
|
||||
XML_ErrorString(XML_GetErrorCode(parser)),
|
||||
XML_GetCurrentLineNumber(parser));
|
||||
return 1;
|
||||
}
|
||||
} while (!done);
|
||||
XML_ParserFree(parser);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,343 @@
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ../../..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
ABYSS_SUBDIR = @ABYSS_SUBDIR@
|
||||
AS = @AS@
|
||||
ASYNCH_CLIENT = @ASYNCH_CLIENT@
|
||||
AUTH_CLIENT = @AUTH_CLIENT@
|
||||
AVAILABLE_MODULES = @AVAILABLE_MODULES@
|
||||
CC = @CC@
|
||||
CC_WARN_FLAGS = @CC_WARN_FLAGS@
|
||||
CLIENTTEST = @CLIENTTEST@
|
||||
CONFIGURE_DATE = @CONFIGURE_DATE@
|
||||
CPPTEST = @CPPTEST@
|
||||
CPP_WARN_FLAGS = @CPP_WARN_FLAGS@
|
||||
CXX = @CXX@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
EFRPCTEST = @EFRPCTEST@
|
||||
EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@
|
||||
INTEROP_CGI = @INTEROP_CGI@
|
||||
INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBWWW_CFLAGS = @LIBWWW_CFLAGS@
|
||||
LIBWWW_CONFIG = @LIBWWW_CONFIG@
|
||||
LIBWWW_LDADD = @LIBWWW_LDADD@
|
||||
LIBWWW_LIBDIR = @LIBWWW_LIBDIR@
|
||||
LIBWWW_RPATH = @LIBWWW_RPATH@
|
||||
LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@
|
||||
LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@
|
||||
LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@
|
||||
LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@
|
||||
LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@
|
||||
LN_S = @LN_S@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MEERKAT_APP_LIST = @MEERKAT_APP_LIST@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
PACKAGE = @PACKAGE@
|
||||
QUERY_MEERKAT = @QUERY_MEERKAT@
|
||||
RANLIB = @RANLIB@
|
||||
SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@
|
||||
SERVER = @SERVER@
|
||||
SERVERTEST = @SERVERTEST@
|
||||
SYNCH_CLIENT = @SYNCH_CLIENT@
|
||||
VALIDATEE = @VALIDATEE@
|
||||
VERSION = @VERSION@
|
||||
VERSION_INFO = @VERSION_INFO@
|
||||
XMLRPCCPP_H = @XMLRPCCPP_H@
|
||||
XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@
|
||||
XMLRPC_CGI_H = @XMLRPC_CGI_H@
|
||||
XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@
|
||||
XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@
|
||||
|
||||
INCLUDES = -I$(srcdir)/../xmltok
|
||||
|
||||
lib_LTLIBRARIES = libxmlrpc_xmlparse.la
|
||||
|
||||
libxmlrpc_xmlparse_la_SOURCES = xmlparse.c xmlparse.h
|
||||
libxmlrpc_xmlparse_la_LDFLAGS = @VERSION_INFO@
|
||||
|
||||
EXTRA_DIST = xmlparse.dsp
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../../../xmlrpc_config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
|
||||
|
||||
DEFS = @DEFS@ -I. -I$(srcdir) -I../../..
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
libxmlrpc_xmlparse_la_LIBADD =
|
||||
libxmlrpc_xmlparse_la_OBJECTS = xmlparse.lo
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
DIST_COMMON = Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
SOURCES = $(libxmlrpc_xmlparse_la_SOURCES)
|
||||
OBJECTS = $(libxmlrpc_xmlparse_la_OBJECTS)
|
||||
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .S .c .lo .o .s
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
|
||||
mostlyclean-libLTLIBRARIES:
|
||||
|
||||
clean-libLTLIBRARIES:
|
||||
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
|
||||
|
||||
distclean-libLTLIBRARIES:
|
||||
|
||||
maintainer-clean-libLTLIBRARIES:
|
||||
|
||||
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p"; \
|
||||
$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(libdir)/$$p; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-libLTLIBRARIES:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
list='$(lib_LTLIBRARIES)'; for p in $$list; do \
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
|
||||
done
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.s.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.S.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.o core *.core
|
||||
|
||||
clean-compile:
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
maintainer-clean-compile:
|
||||
|
||||
.c.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.s.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
.S.lo:
|
||||
$(LIBTOOL) --mode=compile $(COMPILE) -c $<
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
distclean-libtool:
|
||||
|
||||
maintainer-clean-libtool:
|
||||
|
||||
libxmlrpc_xmlparse.la: $(libxmlrpc_xmlparse_la_OBJECTS) $(libxmlrpc_xmlparse_la_DEPENDENCIES)
|
||||
$(LINK) -rpath $(libdir) $(libxmlrpc_xmlparse_la_LDFLAGS) $(libxmlrpc_xmlparse_la_OBJECTS) $(libxmlrpc_xmlparse_la_LIBADD) $(LIBS)
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $$unique $(LISP)
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = lib/expat/xmlparse
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
xmlparse.lo xmlparse.o : xmlparse.c ../xmltok/xmldef.h xmlparse.h \
|
||||
../xmltok/xmltok.h ../xmltok/xmlrole.h
|
||||
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-exec-am: install-libLTLIBRARIES
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am: uninstall-libLTLIBRARIES
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile $(LTLIBRARIES)
|
||||
all-redirect: all-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-libLTLIBRARIES mostlyclean-compile \
|
||||
mostlyclean-libtool mostlyclean-tags \
|
||||
mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-libLTLIBRARIES clean-compile clean-libtool clean-tags \
|
||||
clean-generic mostlyclean-am
|
||||
|
||||
clean: clean-am
|
||||
|
||||
distclean-am: distclean-libLTLIBRARIES distclean-compile \
|
||||
distclean-libtool distclean-tags distclean-generic \
|
||||
clean-am
|
||||
-rm -f libtool
|
||||
|
||||
distclean: distclean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-libLTLIBRARIES \
|
||||
maintainer-clean-compile maintainer-clean-libtool \
|
||||
maintainer-clean-tags maintainer-clean-generic \
|
||||
distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
.PHONY: mostlyclean-libLTLIBRARIES distclean-libLTLIBRARIES \
|
||||
clean-libLTLIBRARIES maintainer-clean-libLTLIBRARIES \
|
||||
uninstall-libLTLIBRARIES install-libLTLIBRARIES mostlyclean-compile \
|
||||
distclean-compile clean-compile maintainer-clean-compile \
|
||||
mostlyclean-libtool distclean-libtool clean-libtool \
|
||||
maintainer-clean-libtool tags mostlyclean-tags distclean-tags \
|
||||
clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
|
||||
check-am installcheck-am installcheck install-exec-am install-exec \
|
||||
install-data-am install-data install-am install uninstall-am uninstall \
|
||||
all-redirect all-am all installdirs mostlyclean-generic \
|
||||
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||
mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,279 @@
|
||||
# Microsoft Developer Studio Project File - Name="xmlparse" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=xmlparse - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "xmlparse.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "xmlparse.mak" CFG="xmlparse - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "xmlparse - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "xmlparse - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "xmlparse - Win32 Release DLL" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "xmlparse - Win32 Debug DLL" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "xmlparse - Win32 MinSize DLL" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "xmlparse"
|
||||
# PROP Scc_LocalPath ".."
|
||||
|
||||
!IF "$(CFG)" == "xmlparse - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release\xmlparse"
|
||||
# PROP Intermediate_Dir "Release\xmlparse"
|
||||
# PROP Target_Dir "."
|
||||
LINK32=link.exe -lib
|
||||
MTL=midl.exe
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\Debug"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug\xmlparse"
|
||||
# PROP Intermediate_Dir "Debug\xmlparse"
|
||||
# PROP Target_Dir "."
|
||||
LINK32=link.exe -lib
|
||||
MTL=midl.exe
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\ReleaseDLL"
|
||||
# PROP BASE Intermediate_Dir ".\ReleaseDLL"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "ReleaseDLL\xmlparse"
|
||||
# PROP Intermediate_Dir "ReleaseDLL\xmlparse"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "XML_NS" /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:I386 /link50compat
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\DebugDLL"
|
||||
# PROP BASE Intermediate_Dir ".\DebugDLL"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugDLL\xmlparse"
|
||||
# PROP Intermediate_Dir "DebugDLL\xmlparse"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x809 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /debug /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\ReleaseMinSizeDLL"
|
||||
# PROP BASE Intermediate_Dir ".\ReleaseMinSizeDLL"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "ReleaseMinSizeDLL\xmlparse"
|
||||
# PROP Intermediate_Dir "ReleaseMinSizeDLL\xmlparse"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "XML_NS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O1 /I "..\xmltok" /I "..\xmlwf" /I "..\..\.." /D "XML_MIN_SIZE" /D "XML_WINLIB" /D XMLPARSEAPI=__declspec(dllexport) /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /FD /c
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /machine:I386
|
||||
# SUBTRACT BASE LINK32 /profile
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x20000000" /entry:"DllMain" /subsystem:windows /dll /machine:I386
|
||||
# SUBTRACT LINK32 /profile /nodefaultlib
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "xmlparse - Win32 Release"
|
||||
# Name "xmlparse - Win32 Debug"
|
||||
# Name "xmlparse - Win32 Release DLL"
|
||||
# Name "xmlparse - Win32 Debug DLL"
|
||||
# Name "xmlparse - Win32 MinSize DLL"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\xmltok\dllmain.c
|
||||
|
||||
!IF "$(CFG)" == "xmlparse - Win32 Release"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL"
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL"
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmlparse.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\xmltok\xmlrole.c
|
||||
|
||||
!IF "$(CFG)" == "xmlparse - Win32 Release"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\xmltok\xmltok.c
|
||||
|
||||
!IF "$(CFG)" == "xmlparse - Win32 Release"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Release DLL"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 Debug DLL"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlparse - Win32 MinSize DLL"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmlparse.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,527 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#ifndef XmlParse_INCLUDED
|
||||
#define XmlParse_INCLUDED 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XMLPARSEAPI
|
||||
#define XMLPARSEAPI /* as nothing */
|
||||
#endif
|
||||
|
||||
typedef void *XML_Parser;
|
||||
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
|
||||
/* XML_UNICODE_WCHAR_T will work only if sizeof(wchar_t) == 2 and wchar_t
|
||||
uses Unicode. */
|
||||
/* Information is UTF-16 encoded as wchar_ts */
|
||||
|
||||
#ifndef XML_UNICODE
|
||||
#define XML_UNICODE
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
typedef wchar_t XML_Char;
|
||||
typedef wchar_t XML_LChar;
|
||||
|
||||
#else /* not XML_UNICODE_WCHAR_T */
|
||||
|
||||
#ifdef XML_UNICODE
|
||||
|
||||
/* Information is UTF-16 encoded as unsigned shorts */
|
||||
typedef unsigned short XML_Char;
|
||||
typedef char XML_LChar;
|
||||
|
||||
#else /* not XML_UNICODE */
|
||||
|
||||
/* Information is UTF-8 encoded. */
|
||||
typedef char XML_Char;
|
||||
typedef char XML_LChar;
|
||||
|
||||
#endif /* not XML_UNICODE */
|
||||
|
||||
#endif /* not XML_UNICODE_WCHAR_T */
|
||||
|
||||
|
||||
/* Constructs a new parser; encoding is the encoding specified by the external
|
||||
protocol or null if there is none specified. */
|
||||
|
||||
XML_Parser XMLPARSEAPI
|
||||
XML_ParserCreate(const XML_Char *encoding);
|
||||
|
||||
/* Constructs a new parser and namespace processor. Element type names
|
||||
and attribute names that belong to a namespace will be expanded;
|
||||
unprefixed attribute names are never expanded; unprefixed element type
|
||||
names are expanded only if there is a default namespace. The expanded
|
||||
name is the concatenation of the namespace URI, the namespace separator character,
|
||||
and the local part of the name. If the namespace separator is '\0' then
|
||||
the namespace URI and the local part will be concatenated without any
|
||||
separator. When a namespace is not declared, the name and prefix will be
|
||||
passed through without expansion. */
|
||||
|
||||
XML_Parser XMLPARSEAPI
|
||||
XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
|
||||
|
||||
|
||||
/* atts is array of name/value pairs, terminated by 0;
|
||||
names and values are 0 terminated. */
|
||||
|
||||
typedef void (*XML_StartElementHandler)(void *userData,
|
||||
const XML_Char *name,
|
||||
const XML_Char **atts);
|
||||
|
||||
typedef void (*XML_EndElementHandler)(void *userData,
|
||||
const XML_Char *name);
|
||||
|
||||
/* s is not 0 terminated. */
|
||||
typedef void (*XML_CharacterDataHandler)(void *userData,
|
||||
const XML_Char *s,
|
||||
int len);
|
||||
|
||||
/* target and data are 0 terminated */
|
||||
typedef void (*XML_ProcessingInstructionHandler)(void *userData,
|
||||
const XML_Char *target,
|
||||
const XML_Char *data);
|
||||
|
||||
/* data is 0 terminated */
|
||||
typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
|
||||
|
||||
typedef void (*XML_StartCdataSectionHandler)(void *userData);
|
||||
typedef void (*XML_EndCdataSectionHandler)(void *userData);
|
||||
|
||||
/* This is called for any characters in the XML document for
|
||||
which there is no applicable handler. This includes both
|
||||
characters that are part of markup which is of a kind that is
|
||||
not reported (comments, markup declarations), or characters
|
||||
that are part of a construct which could be reported but
|
||||
for which no handler has been supplied. The characters are passed
|
||||
exactly as they were in the XML document except that
|
||||
they will be encoded in UTF-8. Line boundaries are not normalized.
|
||||
Note that a byte order mark character is not passed to the default handler.
|
||||
There are no guarantees about how characters are divided between calls
|
||||
to the default handler: for example, a comment might be split between
|
||||
multiple calls. */
|
||||
|
||||
typedef void (*XML_DefaultHandler)(void *userData,
|
||||
const XML_Char *s,
|
||||
int len);
|
||||
|
||||
/* This is called for the start of the DOCTYPE declaration when the
|
||||
name of the DOCTYPE is encountered. */
|
||||
typedef void (*XML_StartDoctypeDeclHandler)(void *userData,
|
||||
const XML_Char *doctypeName);
|
||||
|
||||
/* This is called for the start of the DOCTYPE declaration when the
|
||||
closing > is encountered, but after processing any external subset. */
|
||||
typedef void (*XML_EndDoctypeDeclHandler)(void *userData);
|
||||
|
||||
/* This is called for a declaration of an unparsed (NDATA)
|
||||
entity. The base argument is whatever was set by XML_SetBase.
|
||||
The entityName, systemId and notationName arguments will never be null.
|
||||
The other arguments may be. */
|
||||
|
||||
typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
|
||||
const XML_Char *entityName,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId,
|
||||
const XML_Char *notationName);
|
||||
|
||||
/* This is called for a declaration of notation.
|
||||
The base argument is whatever was set by XML_SetBase.
|
||||
The notationName will never be null. The other arguments can be. */
|
||||
|
||||
typedef void (*XML_NotationDeclHandler)(void *userData,
|
||||
const XML_Char *notationName,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId);
|
||||
|
||||
typedef void (*XML_ExternalParsedEntityDeclHandler)(void *userData,
|
||||
const XML_Char *entityName,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId);
|
||||
|
||||
typedef void (*XML_InternalParsedEntityDeclHandler)(void *userData,
|
||||
const XML_Char *entityName,
|
||||
const XML_Char *replacementText,
|
||||
int replacementTextLength);
|
||||
|
||||
/* When namespace processing is enabled, these are called once for
|
||||
each namespace declaration. The call to the start and end element
|
||||
handlers occur between the calls to the start and end namespace
|
||||
declaration handlers. For an xmlns attribute, prefix will be null.
|
||||
For an xmlns="" attribute, uri will be null. */
|
||||
|
||||
typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
|
||||
const XML_Char *prefix,
|
||||
const XML_Char *uri);
|
||||
|
||||
typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
|
||||
const XML_Char *prefix);
|
||||
|
||||
/* This is called if the document is not standalone (it has an
|
||||
external subset or a reference to a parameter entity, but does not
|
||||
have standalone="yes"). If this handler returns 0, then processing
|
||||
will not continue, and the parser will return a
|
||||
XML_ERROR_NOT_STANDALONE error. */
|
||||
|
||||
typedef int (*XML_NotStandaloneHandler)(void *userData);
|
||||
|
||||
/* This is called for a reference to an external parsed general entity.
|
||||
The referenced entity is not automatically parsed.
|
||||
The application can parse it immediately or later using
|
||||
XML_ExternalEntityParserCreate.
|
||||
The parser argument is the parser parsing the entity containing the reference;
|
||||
it can be passed as the parser argument to XML_ExternalEntityParserCreate.
|
||||
The systemId argument is the system identifier as specified in the entity declaration;
|
||||
it will not be null.
|
||||
The base argument is the system identifier that should be used as the base for
|
||||
resolving systemId if systemId was relative; this is set by XML_SetBase;
|
||||
it may be null.
|
||||
The publicId argument is the public identifier as specified in the entity declaration,
|
||||
or null if none was specified; the whitespace in the public identifier
|
||||
will have been normalized as required by the XML spec.
|
||||
The context argument specifies the parsing context in the format
|
||||
expected by the context argument to
|
||||
XML_ExternalEntityParserCreate; context is valid only until the handler
|
||||
returns, so if the referenced entity is to be parsed later, it must be copied.
|
||||
The handler should return 0 if processing should not continue because of
|
||||
a fatal error in the handling of the external entity.
|
||||
In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING
|
||||
error.
|
||||
Note that unlike other handlers the first argument is the parser, not userData. */
|
||||
|
||||
typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
|
||||
const XML_Char *context,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId);
|
||||
|
||||
/* This structure is filled in by the XML_UnknownEncodingHandler
|
||||
to provide information to the parser about encodings that are unknown
|
||||
to the parser.
|
||||
The map[b] member gives information about byte sequences
|
||||
whose first byte is b.
|
||||
If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c.
|
||||
If map[b] is -1, then the byte sequence is malformed.
|
||||
If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
|
||||
sequence that encodes a single Unicode scalar value.
|
||||
The data member will be passed as the first argument to the convert function.
|
||||
The convert function is used to convert multibyte sequences;
|
||||
s will point to a n-byte sequence where map[(unsigned char)*s] == -n.
|
||||
The convert function must return the Unicode scalar value
|
||||
represented by this byte sequence or -1 if the byte sequence is malformed.
|
||||
The convert function may be null if the encoding is a single-byte encoding,
|
||||
that is if map[b] >= -1 for all bytes b.
|
||||
When the parser is finished with the encoding, then if release is not null,
|
||||
it will call release passing it the data member;
|
||||
once release has been called, the convert function will not be called again.
|
||||
|
||||
Expat places certain restrictions on the encodings that are supported
|
||||
using this mechanism.
|
||||
|
||||
1. Every ASCII character that can appear in a well-formed XML document,
|
||||
other than the characters
|
||||
|
||||
$@\^`{}~
|
||||
|
||||
must be represented by a single byte, and that byte must be the
|
||||
same byte that represents that character in ASCII.
|
||||
|
||||
2. No character may require more than 4 bytes to encode.
|
||||
|
||||
3. All characters encoded must have Unicode scalar values <= 0xFFFF,
|
||||
(ie characters that would be encoded by surrogates in UTF-16
|
||||
are not allowed). Note that this restriction doesn't apply to
|
||||
the built-in support for UTF-8 and UTF-16.
|
||||
|
||||
4. No Unicode character may be encoded by more than one distinct sequence
|
||||
of bytes. */
|
||||
|
||||
typedef struct {
|
||||
int map[256];
|
||||
void *data;
|
||||
int (*convert)(void *data, const char *s);
|
||||
void (*release)(void *data);
|
||||
} XML_Encoding;
|
||||
|
||||
/* This is called for an encoding that is unknown to the parser.
|
||||
The encodingHandlerData argument is that which was passed as the
|
||||
second argument to XML_SetUnknownEncodingHandler.
|
||||
The name argument gives the name of the encoding as specified in
|
||||
the encoding declaration.
|
||||
If the callback can provide information about the encoding,
|
||||
it must fill in the XML_Encoding structure, and return 1.
|
||||
Otherwise it must return 0.
|
||||
If info does not describe a suitable encoding,
|
||||
then the parser will return an XML_UNKNOWN_ENCODING error. */
|
||||
|
||||
typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
|
||||
const XML_Char *name,
|
||||
XML_Encoding *info);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetElementHandler(XML_Parser parser,
|
||||
XML_StartElementHandler start,
|
||||
XML_EndElementHandler end);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetCharacterDataHandler(XML_Parser parser,
|
||||
XML_CharacterDataHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetProcessingInstructionHandler(XML_Parser parser,
|
||||
XML_ProcessingInstructionHandler handler);
|
||||
void XMLPARSEAPI
|
||||
XML_SetCommentHandler(XML_Parser parser,
|
||||
XML_CommentHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetCdataSectionHandler(XML_Parser parser,
|
||||
XML_StartCdataSectionHandler start,
|
||||
XML_EndCdataSectionHandler end);
|
||||
|
||||
/* This sets the default handler and also inhibits expansion of internal entities.
|
||||
The entity reference will be passed to the default handler. */
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetDefaultHandler(XML_Parser parser,
|
||||
XML_DefaultHandler handler);
|
||||
|
||||
/* This sets the default handler but does not inhibit expansion of internal entities.
|
||||
The entity reference will not be passed to the default handler. */
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetDefaultHandlerExpand(XML_Parser parser,
|
||||
XML_DefaultHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetDoctypeDeclHandler(XML_Parser parser,
|
||||
XML_StartDoctypeDeclHandler start,
|
||||
XML_EndDoctypeDeclHandler end);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
|
||||
XML_UnparsedEntityDeclHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetNotationDeclHandler(XML_Parser parser,
|
||||
XML_NotationDeclHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetExternalParsedEntityDeclHandler(XML_Parser parser,
|
||||
XML_ExternalParsedEntityDeclHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetInternalParsedEntityDeclHandler(XML_Parser parser,
|
||||
XML_InternalParsedEntityDeclHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetNamespaceDeclHandler(XML_Parser parser,
|
||||
XML_StartNamespaceDeclHandler start,
|
||||
XML_EndNamespaceDeclHandler end);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetNotStandaloneHandler(XML_Parser parser,
|
||||
XML_NotStandaloneHandler handler);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetExternalEntityRefHandler(XML_Parser parser,
|
||||
XML_ExternalEntityRefHandler handler);
|
||||
|
||||
/* If a non-null value for arg is specified here, then it will be passed
|
||||
as the first argument to the external entity ref handler instead
|
||||
of the parser object. */
|
||||
void XMLPARSEAPI
|
||||
XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_SetUnknownEncodingHandler(XML_Parser parser,
|
||||
XML_UnknownEncodingHandler handler,
|
||||
void *encodingHandlerData);
|
||||
|
||||
/* This can be called within a handler for a start element, end element,
|
||||
processing instruction or character data. It causes the corresponding
|
||||
markup to be passed to the default handler. */
|
||||
void XMLPARSEAPI XML_DefaultCurrent(XML_Parser parser);
|
||||
|
||||
/* This value is passed as the userData argument to callbacks. */
|
||||
void XMLPARSEAPI
|
||||
XML_SetUserData(XML_Parser parser, void *userData);
|
||||
|
||||
/* Returns the last value set by XML_SetUserData or null. */
|
||||
#define XML_GetUserData(parser) (*(void **)(parser))
|
||||
|
||||
/* This is equivalent to supplying an encoding argument
|
||||
to XML_ParserCreate. It must not be called after XML_Parse
|
||||
or XML_ParseBuffer. */
|
||||
|
||||
int XMLPARSEAPI
|
||||
XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
|
||||
|
||||
/* If this function is called, then the parser will be passed
|
||||
as the first argument to callbacks instead of userData.
|
||||
The userData will still be accessible using XML_GetUserData. */
|
||||
|
||||
void XMLPARSEAPI
|
||||
XML_UseParserAsHandlerArg(XML_Parser parser);
|
||||
|
||||
/* Sets the base to be used for resolving relative URIs in system identifiers in
|
||||
declarations. Resolving relative identifiers is left to the application:
|
||||
this value will be passed through as the base argument to the
|
||||
XML_ExternalEntityRefHandler, XML_NotationDeclHandler
|
||||
and XML_UnparsedEntityDeclHandler. The base argument will be copied.
|
||||
Returns zero if out of memory, non-zero otherwise. */
|
||||
|
||||
int XMLPARSEAPI
|
||||
XML_SetBase(XML_Parser parser, const XML_Char *base);
|
||||
|
||||
const XML_Char XMLPARSEAPI *
|
||||
XML_GetBase(XML_Parser parser);
|
||||
|
||||
/* Returns the number of the attribute/value pairs passed in last call
|
||||
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. */
|
||||
|
||||
int XMLPARSEAPI 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. */
|
||||
int XMLPARSEAPI XML_GetIdAttributeIndex(XML_Parser parser);
|
||||
|
||||
/* Parses some input. Returns 0 if a fatal error is detected.
|
||||
The last call to XML_Parse must have isFinal true;
|
||||
len may be zero for this call (or any other). */
|
||||
int XMLPARSEAPI
|
||||
XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
|
||||
|
||||
void XMLPARSEAPI *
|
||||
XML_GetBuffer(XML_Parser parser, int len);
|
||||
|
||||
int XMLPARSEAPI
|
||||
XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
|
||||
|
||||
/* Creates an XML_Parser object that can parse an external general entity;
|
||||
context is a '\0'-terminated string specifying the parse context;
|
||||
encoding is a '\0'-terminated string giving the name of the externally specified encoding,
|
||||
or null if there is no externally specified encoding.
|
||||
The context string consists of a sequence of tokens separated by formfeeds (\f);
|
||||
a token consisting of a name specifies that the general entity of the name
|
||||
is open; a token of the form prefix=uri specifies the namespace for a particular
|
||||
prefix; a token of the form =uri specifies the default namespace.
|
||||
This can be called at any point after the first call to an ExternalEntityRefHandler
|
||||
so longer as the parser has not yet been freed.
|
||||
The new parser is completely independent and may safely be used in a separate thread.
|
||||
The handlers and userData are initialized from the parser argument.
|
||||
Returns 0 if out of memory. Otherwise returns a new XML_Parser object. */
|
||||
XML_Parser XMLPARSEAPI
|
||||
XML_ExternalEntityParserCreate(XML_Parser parser,
|
||||
const XML_Char *context,
|
||||
const XML_Char *encoding);
|
||||
|
||||
enum XML_ParamEntityParsing {
|
||||
XML_PARAM_ENTITY_PARSING_NEVER,
|
||||
XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
|
||||
XML_PARAM_ENTITY_PARSING_ALWAYS
|
||||
};
|
||||
|
||||
/* Controls parsing of parameter entities (including the external DTD
|
||||
subset). If parsing of parameter entities is enabled, then references
|
||||
to external parameter entities (including the external DTD subset)
|
||||
will be passed to the handler set with
|
||||
XML_SetExternalEntityRefHandler. The context passed will be 0.
|
||||
Unlike external general entities, external parameter entities can only
|
||||
be parsed synchronously. If the external parameter entity is to be
|
||||
parsed, it must be parsed during the call to the external entity ref
|
||||
handler: the complete sequence of XML_ExternalEntityParserCreate,
|
||||
XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during
|
||||
this call. After XML_ExternalEntityParserCreate has been called to
|
||||
create the parser for the external parameter entity (context must be 0
|
||||
for this call), it is illegal to make any calls on the old parser
|
||||
until XML_ParserFree has been called on the newly created parser. If
|
||||
the library has been compiled without support for parameter entity
|
||||
parsing (ie without XML_DTD being defined), then
|
||||
XML_SetParamEntityParsing will return 0 if parsing of parameter
|
||||
entities is requested; otherwise it will return non-zero. */
|
||||
|
||||
int XMLPARSEAPI
|
||||
XML_SetParamEntityParsing(XML_Parser parser,
|
||||
enum XML_ParamEntityParsing parsing);
|
||||
|
||||
enum XML_Error {
|
||||
XML_ERROR_NONE,
|
||||
XML_ERROR_NO_MEMORY,
|
||||
XML_ERROR_SYNTAX,
|
||||
XML_ERROR_NO_ELEMENTS,
|
||||
XML_ERROR_INVALID_TOKEN,
|
||||
XML_ERROR_UNCLOSED_TOKEN,
|
||||
XML_ERROR_PARTIAL_CHAR,
|
||||
XML_ERROR_TAG_MISMATCH,
|
||||
XML_ERROR_DUPLICATE_ATTRIBUTE,
|
||||
XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
|
||||
XML_ERROR_PARAM_ENTITY_REF,
|
||||
XML_ERROR_UNDEFINED_ENTITY,
|
||||
XML_ERROR_RECURSIVE_ENTITY_REF,
|
||||
XML_ERROR_ASYNC_ENTITY,
|
||||
XML_ERROR_BAD_CHAR_REF,
|
||||
XML_ERROR_BINARY_ENTITY_REF,
|
||||
XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
|
||||
XML_ERROR_MISPLACED_XML_PI,
|
||||
XML_ERROR_UNKNOWN_ENCODING,
|
||||
XML_ERROR_INCORRECT_ENCODING,
|
||||
XML_ERROR_UNCLOSED_CDATA_SECTION,
|
||||
XML_ERROR_EXTERNAL_ENTITY_HANDLING,
|
||||
XML_ERROR_NOT_STANDALONE
|
||||
};
|
||||
|
||||
/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode
|
||||
returns information about the error. */
|
||||
|
||||
enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser);
|
||||
|
||||
/* These functions return information about the current parse location.
|
||||
They may be called when XML_Parse or XML_ParseBuffer return 0;
|
||||
in this case the location is the location of the character at which
|
||||
the error was detected.
|
||||
They may also be called from any other callback called to report
|
||||
some parse event; in this the location is the location of the first
|
||||
of the sequence of characters that generated the event. */
|
||||
|
||||
int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser);
|
||||
int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser);
|
||||
long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser);
|
||||
|
||||
/* Return the number of bytes in the current event.
|
||||
Returns 0 if the event is in an internal entity. */
|
||||
|
||||
int XMLPARSEAPI XML_GetCurrentByteCount(XML_Parser parser);
|
||||
|
||||
/* For backwards compatibility with previous versions. */
|
||||
#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
|
||||
#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
|
||||
#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
|
||||
|
||||
/* Frees memory used by the parser. */
|
||||
void XMLPARSEAPI
|
||||
XML_ParserFree(XML_Parser parser);
|
||||
|
||||
/* Returns a string describing the error. */
|
||||
const XML_LChar XMLPARSEAPI *XML_ErrorString(int code);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* not XmlParse_INCLUDED */
|
||||
@@ -0,0 +1 @@
|
||||
nametab.h
|
||||
@@ -0,0 +1,66 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../../..
|
||||
endif
|
||||
|
||||
include $(SRCDIR)/Makefile.config
|
||||
|
||||
# I can't figure out what XML_BYTE_ORDER is, but it doesn't look like the
|
||||
# code has ever defined it. That means it's treated like 0 in #if. Since
|
||||
# we started using the Gcc -Wundef option, that generates a warning, so
|
||||
# se set it explicitly to 0 here.
|
||||
|
||||
CFLAGS = $(CFLAGS_COMMON) -DXML_BYTE_ORDER=0 $(CFLAGS_PERSONAL) $(CADD)
|
||||
|
||||
LIBLDFLAGS = $(LDFLAGS_VERSINFO) -rpath $(LIBINST_DIR) $(LADD)
|
||||
|
||||
INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/lib/util/include
|
||||
|
||||
default: all
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
.PHONY: all
|
||||
all: libxmlrpc_xmltok.la
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-common
|
||||
rm -f nametab.h
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean distclean-common
|
||||
|
||||
.PHONY: tags
|
||||
tags: TAGS
|
||||
|
||||
.PHONY: distdir
|
||||
distdir:
|
||||
|
||||
.PHONY: install
|
||||
install: install-common
|
||||
|
||||
.PHONY: dep
|
||||
dep: dep-common
|
||||
|
||||
LTLIBRARIES_TO_INSTALL = libxmlrpc_xmltok.la
|
||||
|
||||
LIBXMLRPC_XMLTOK_OBJS = xmltok.lo xmlrole.lo
|
||||
|
||||
libxmlrpc_xmltok.la: $(LIBXMLRPC_XMLTOK_OBJS)
|
||||
$(LIBTOOL) --mode=link $(CCLD) -o $@ $(LIBLDFLAGS) $^
|
||||
|
||||
$(LIBXMLRPC_XMLTOK_OBJS):%.lo:%.c
|
||||
$(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(LIBXML_INCLUDES) \
|
||||
$(CFLAGS) $<
|
||||
|
||||
GENNMTAB = ../gennmtab/gennmtab
|
||||
|
||||
nametab.h: $(GENNMTAB)
|
||||
rm -f $@
|
||||
$(GENNMTAB) >$@ || rm -f $@
|
||||
|
||||
$(GENNMTAB):
|
||||
$(MAKE) -C $(dir $@) $(notdir $@)
|
||||
|
||||
xmltok.lo: nametab.h
|
||||
|
||||
include Makefile.depend
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#define ASCII_A 0x41
|
||||
#define ASCII_B 0x42
|
||||
#define ASCII_C 0x43
|
||||
#define ASCII_D 0x44
|
||||
#define ASCII_E 0x45
|
||||
#define ASCII_F 0x46
|
||||
#define ASCII_G 0x47
|
||||
#define ASCII_H 0x48
|
||||
#define ASCII_I 0x49
|
||||
#define ASCII_J 0x4A
|
||||
#define ASCII_K 0x4B
|
||||
#define ASCII_L 0x4C
|
||||
#define ASCII_M 0x4D
|
||||
#define ASCII_N 0x4E
|
||||
#define ASCII_O 0x4F
|
||||
#define ASCII_P 0x50
|
||||
#define ASCII_Q 0x51
|
||||
#define ASCII_R 0x52
|
||||
#define ASCII_S 0x53
|
||||
#define ASCII_T 0x54
|
||||
#define ASCII_U 0x55
|
||||
#define ASCII_V 0x56
|
||||
#define ASCII_W 0x57
|
||||
#define ASCII_X 0x58
|
||||
#define ASCII_Y 0x59
|
||||
#define ASCII_Z 0x5A
|
||||
|
||||
#define ASCII_a 0x61
|
||||
#define ASCII_b 0x62
|
||||
#define ASCII_c 0x63
|
||||
#define ASCII_d 0x64
|
||||
#define ASCII_e 0x65
|
||||
#define ASCII_f 0x66
|
||||
#define ASCII_g 0x67
|
||||
#define ASCII_h 0x68
|
||||
#define ASCII_i 0x69
|
||||
#define ASCII_j 0x6A
|
||||
#define ASCII_k 0x6B
|
||||
#define ASCII_l 0x6C
|
||||
#define ASCII_m 0x6D
|
||||
#define ASCII_n 0x6E
|
||||
#define ASCII_o 0x6F
|
||||
#define ASCII_p 0x70
|
||||
#define ASCII_q 0x71
|
||||
#define ASCII_r 0x72
|
||||
#define ASCII_s 0x73
|
||||
#define ASCII_t 0x74
|
||||
#define ASCII_u 0x75
|
||||
#define ASCII_v 0x76
|
||||
#define ASCII_w 0x77
|
||||
#define ASCII_x 0x78
|
||||
#define ASCII_y 0x79
|
||||
#define ASCII_z 0x7A
|
||||
|
||||
#define ASCII_0 0x30
|
||||
#define ASCII_1 0x31
|
||||
#define ASCII_2 0x32
|
||||
#define ASCII_3 0x33
|
||||
#define ASCII_4 0x34
|
||||
#define ASCII_5 0x35
|
||||
#define ASCII_6 0x36
|
||||
#define ASCII_7 0x37
|
||||
#define ASCII_8 0x38
|
||||
#define ASCII_9 0x39
|
||||
|
||||
#define ASCII_TAB 0x09
|
||||
#define ASCII_SPACE 0x20
|
||||
#define ASCII_EXCL 0x21
|
||||
#define ASCII_QUOT 0x22
|
||||
#define ASCII_AMP 0x26
|
||||
#define ASCII_APOS 0x27
|
||||
#define ASCII_MINUS 0x2D
|
||||
#define ASCII_PERIOD 0x2E
|
||||
#define ASCII_COLON 0x3A
|
||||
#define ASCII_SEMI 0x3B
|
||||
#define ASCII_LT 0x3C
|
||||
#define ASCII_EQUALS 0x3D
|
||||
#define ASCII_GT 0x3E
|
||||
#define ASCII_LSQB 0x5B
|
||||
#define ASCII_RSQB 0x5D
|
||||
#define ASCII_UNDERSCORE 0x5F
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
|
||||
/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
|
||||
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
|
||||
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
|
||||
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
|
||||
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
|
||||
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
|
||||
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
|
||||
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
|
||||
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
|
||||
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#define STRICT 1
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
|
||||
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
|
||||
/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
|
||||
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
|
||||
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
|
||||
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
|
||||
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
|
||||
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
|
||||
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
|
||||
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
|
||||
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
|
||||
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
|
||||
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
|
||||
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
|
||||
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
|
||||
/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
|
||||
/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
|
||||
/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
|
||||
/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
|
||||
/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
|
||||
/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
|
||||
/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
|
||||
/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
|
||||
/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
|
||||
/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
|
||||
/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
|
||||
/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef XML_WINLIB
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define STRICT
|
||||
#include <windows.h>
|
||||
|
||||
#define malloc(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
||||
#define calloc(x, y) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)*(y))
|
||||
#define free(x) HeapFree(GetProcessHeap(), 0, (x))
|
||||
#define realloc(x, y) HeapReAlloc(GetProcessHeap(), 0, x, y)
|
||||
#define abort() /* as nothing */
|
||||
|
||||
#else /* not XML_WINLIB */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#endif /* not XML_WINLIB */
|
||||
|
||||
/* This file can be used for any definitions needed in
|
||||
particular environments. */
|
||||
|
||||
/* Mozilla specific defines */
|
||||
|
||||
#ifdef MOZILLA_CLIENT
|
||||
|
||||
#include "nspr.h"
|
||||
#define malloc(x) PR_Malloc((size_t)(x))
|
||||
#define realloc(x, y) PR_Realloc((x), (size_t)(y))
|
||||
#define calloc(x, y) PR_Calloc((x),(y))
|
||||
#define free(x) PR_Free(x)
|
||||
#if PR_BYTES_PER_INT != 4
|
||||
#define int int32
|
||||
#endif
|
||||
|
||||
/* Enable Unicode string processing in expat. */
|
||||
#ifndef XML_UNICODE
|
||||
#define XML_UNICODE
|
||||
#endif
|
||||
|
||||
/* Enable external parameter entity parsing in expat */
|
||||
#ifndef XML_DTD
|
||||
#define XML_DTD 1
|
||||
#endif
|
||||
|
||||
#endif /* MOZILLA_CLIENT */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#ifndef XmlRole_INCLUDED
|
||||
#define XmlRole_INCLUDED 1
|
||||
|
||||
#include "xmltok.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
XML_ROLE_ERROR = -1,
|
||||
XML_ROLE_NONE = 0,
|
||||
XML_ROLE_XML_DECL,
|
||||
XML_ROLE_INSTANCE_START,
|
||||
XML_ROLE_DOCTYPE_NAME,
|
||||
XML_ROLE_DOCTYPE_SYSTEM_ID,
|
||||
XML_ROLE_DOCTYPE_PUBLIC_ID,
|
||||
XML_ROLE_DOCTYPE_CLOSE,
|
||||
XML_ROLE_GENERAL_ENTITY_NAME,
|
||||
XML_ROLE_PARAM_ENTITY_NAME,
|
||||
XML_ROLE_ENTITY_VALUE,
|
||||
XML_ROLE_ENTITY_SYSTEM_ID,
|
||||
XML_ROLE_ENTITY_PUBLIC_ID,
|
||||
XML_ROLE_ENTITY_NOTATION_NAME,
|
||||
XML_ROLE_NOTATION_NAME,
|
||||
XML_ROLE_NOTATION_SYSTEM_ID,
|
||||
XML_ROLE_NOTATION_NO_SYSTEM_ID,
|
||||
XML_ROLE_NOTATION_PUBLIC_ID,
|
||||
XML_ROLE_ATTRIBUTE_NAME,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_CDATA,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_ID,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_IDREF,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
|
||||
XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
|
||||
XML_ROLE_ATTRIBUTE_ENUM_VALUE,
|
||||
XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
|
||||
XML_ROLE_ATTLIST_ELEMENT_NAME,
|
||||
XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
|
||||
XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
|
||||
XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
|
||||
XML_ROLE_FIXED_ATTRIBUTE_VALUE,
|
||||
XML_ROLE_ELEMENT_NAME,
|
||||
XML_ROLE_CONTENT_ANY,
|
||||
XML_ROLE_CONTENT_EMPTY,
|
||||
XML_ROLE_CONTENT_PCDATA,
|
||||
XML_ROLE_GROUP_OPEN,
|
||||
XML_ROLE_GROUP_CLOSE,
|
||||
XML_ROLE_GROUP_CLOSE_REP,
|
||||
XML_ROLE_GROUP_CLOSE_OPT,
|
||||
XML_ROLE_GROUP_CLOSE_PLUS,
|
||||
XML_ROLE_GROUP_CHOICE,
|
||||
XML_ROLE_GROUP_SEQUENCE,
|
||||
XML_ROLE_CONTENT_ELEMENT,
|
||||
XML_ROLE_CONTENT_ELEMENT_REP,
|
||||
XML_ROLE_CONTENT_ELEMENT_OPT,
|
||||
XML_ROLE_CONTENT_ELEMENT_PLUS,
|
||||
#ifdef XML_DTD
|
||||
XML_ROLE_TEXT_DECL,
|
||||
XML_ROLE_IGNORE_SECT,
|
||||
XML_ROLE_INNER_PARAM_ENTITY_REF,
|
||||
#endif /* XML_DTD */
|
||||
XML_ROLE_PARAM_ENTITY_REF,
|
||||
XML_ROLE_EXTERNAL_GENERAL_ENTITY_NO_NOTATION
|
||||
};
|
||||
|
||||
typedef struct prolog_state {
|
||||
int (*handler)(struct prolog_state *state,
|
||||
int tok,
|
||||
const char *ptr,
|
||||
const char *end,
|
||||
const ENCODING *enc);
|
||||
unsigned level;
|
||||
#ifdef XML_DTD
|
||||
unsigned includeLevel;
|
||||
int documentEntity;
|
||||
#endif /* XML_DTD */
|
||||
} PROLOG_STATE;
|
||||
|
||||
void XMLTOKAPI XmlPrologStateInit(PROLOG_STATE *);
|
||||
#ifdef XML_DTD
|
||||
void XMLTOKAPI XmlPrologStateInitExternalEntity(PROLOG_STATE *);
|
||||
#endif /* XML_DTD */
|
||||
|
||||
#define XmlTokenRole(state, tok, ptr, end, enc) \
|
||||
(((state)->handler)(state, tok, ptr, end, enc))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* not XmlRole_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,259 @@
|
||||
# Microsoft Developer Studio Project File - Name="xmltok" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=xmltok - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "xmltok.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "xmltok.mak" CFG="xmltok - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "xmltok - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "xmltok - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "xmltok - Win32 Release DLL" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "xmltok - Win32 Debug DLL" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "xmltok"
|
||||
# PROP Scc_LocalPath ".."
|
||||
|
||||
!IF "$(CFG)" == "xmltok - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release\xmltok"
|
||||
# PROP Intermediate_Dir "Release\xmltok"
|
||||
# PROP Target_Dir "."
|
||||
LINK32=link.exe -lib
|
||||
MTL=midl.exe
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\.." /D "NDEBUG" /D "XML_NS" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\Debug"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug\xmltok"
|
||||
# PROP Intermediate_Dir "Debug\xmltok"
|
||||
# PROP Target_Dir "."
|
||||
LINK32=link.exe -lib
|
||||
MTL=midl.exe
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Release DLL"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\ReleaseDLL"
|
||||
# PROP BASE Intermediate_Dir ".\ReleaseDLL"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "ReleaseDLL\xmltok"
|
||||
# PROP Intermediate_Dir "ReleaseDLL\xmltok"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\.." /D "NDEBUG" /D "XML_NS" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /YX /FD /c
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"DllMain" /subsystem:windows /dll /machine:I386 /out:"..\..\xmltok.dll" /link50compat
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Debug DLL"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\DebugDLL"
|
||||
# PROP BASE Intermediate_Dir ".\DebugDLL"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugDLL\xmltok"
|
||||
# PROP Intermediate_Dir "DebugDLL\xmltok"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\.." /D "_DEBUG" /D XMLTOKAPI=__declspec(dllexport) /D "WIN32" /D "_WINDOWS" /D "XML_DTD" /D "XML_NS" /YX /FD /c
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
RSC=rc.exe
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x809 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"..\..\xmltokD.dll"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "xmltok - Win32 Release"
|
||||
# Name "xmltok - Win32 Debug"
|
||||
# Name "xmltok - Win32 Release DLL"
|
||||
# Name "xmltok - Win32 Debug DLL"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dllmain.c
|
||||
|
||||
!IF "$(CFG)" == "xmltok - Win32 Release"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Debug"
|
||||
|
||||
# PROP Exclude_From_Build 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Release DLL"
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Debug DLL"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\gennmtab\gennmtab.c
|
||||
|
||||
!IF "$(CFG)" == "xmltok - Win32 Release"
|
||||
|
||||
# PROP Ignore_Default_Tool 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Debug"
|
||||
|
||||
# PROP Ignore_Default_Tool 1
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Release DLL"
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmltok - Win32 Debug DLL"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmlrole.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmltok.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmltok_impl.c
|
||||
# PROP BASE Exclude_From_Build 1
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmltok_ns.c
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asciitab.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\iasciitab.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\latin1tab.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nametab.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\utf8tab.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmldef.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmlrole.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmltok.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmltok_impl.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#ifndef XmlTok_INCLUDED
|
||||
#define XmlTok_INCLUDED 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef XMLTOKAPI
|
||||
#define XMLTOKAPI /* as nothing */
|
||||
#endif
|
||||
|
||||
/* The following token may be returned by XmlContentTok */
|
||||
#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of
|
||||
illegal ]]> sequence */
|
||||
/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
|
||||
#define XML_TOK_NONE -4 /* The string to be scanned is empty */
|
||||
#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
|
||||
might be part of CRLF sequence */
|
||||
#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
|
||||
#define XML_TOK_PARTIAL -1 /* only part of a token */
|
||||
#define XML_TOK_INVALID 0
|
||||
|
||||
/* The following tokens are returned by XmlContentTok; some are also
|
||||
returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */
|
||||
|
||||
#define XML_TOK_START_TAG_WITH_ATTS 1
|
||||
#define XML_TOK_START_TAG_NO_ATTS 2
|
||||
#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
|
||||
#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
|
||||
#define XML_TOK_END_TAG 5
|
||||
#define XML_TOK_DATA_CHARS 6
|
||||
#define XML_TOK_DATA_NEWLINE 7
|
||||
#define XML_TOK_CDATA_SECT_OPEN 8
|
||||
#define XML_TOK_ENTITY_REF 9
|
||||
#define XML_TOK_CHAR_REF 10 /* numeric character reference */
|
||||
|
||||
/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
|
||||
#define XML_TOK_PI 11 /* processing instruction */
|
||||
#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
|
||||
#define XML_TOK_COMMENT 13
|
||||
#define XML_TOK_BOM 14 /* Byte order mark */
|
||||
|
||||
/* The following tokens are returned only by XmlPrologTok */
|
||||
#define XML_TOK_PROLOG_S 15
|
||||
#define XML_TOK_DECL_OPEN 16 /* <!foo */
|
||||
#define XML_TOK_DECL_CLOSE 17 /* > */
|
||||
#define XML_TOK_NAME 18
|
||||
#define XML_TOK_NMTOKEN 19
|
||||
#define XML_TOK_POUND_NAME 20 /* #name */
|
||||
#define XML_TOK_OR 21 /* | */
|
||||
#define XML_TOK_PERCENT 22
|
||||
#define XML_TOK_OPEN_PAREN 23
|
||||
#define XML_TOK_CLOSE_PAREN 24
|
||||
#define XML_TOK_OPEN_BRACKET 25
|
||||
#define XML_TOK_CLOSE_BRACKET 26
|
||||
#define XML_TOK_LITERAL 27
|
||||
#define XML_TOK_PARAM_ENTITY_REF 28
|
||||
#define XML_TOK_INSTANCE_START 29
|
||||
|
||||
/* The following occur only in element type declarations */
|
||||
#define XML_TOK_NAME_QUESTION 30 /* name? */
|
||||
#define XML_TOK_NAME_ASTERISK 31 /* name* */
|
||||
#define XML_TOK_NAME_PLUS 32 /* name+ */
|
||||
#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
|
||||
#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
|
||||
#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
|
||||
#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
|
||||
#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
|
||||
#define XML_TOK_COMMA 38
|
||||
|
||||
/* The following token is returned only by XmlAttributeValueTok */
|
||||
#define XML_TOK_ATTRIBUTE_VALUE_S 39
|
||||
|
||||
/* The following token is returned only by XmlCdataSectionTok */
|
||||
#define XML_TOK_CDATA_SECT_CLOSE 40
|
||||
|
||||
/* With namespace processing this is returned by XmlPrologTok
|
||||
for a name with a colon. */
|
||||
#define XML_TOK_PREFIXED_NAME 41
|
||||
|
||||
#ifdef XML_DTD
|
||||
#define XML_TOK_IGNORE_SECT 42
|
||||
#endif /* XML_DTD */
|
||||
|
||||
#ifdef XML_DTD
|
||||
#define XML_N_STATES 4
|
||||
#else /* not XML_DTD */
|
||||
#define XML_N_STATES 3
|
||||
#endif /* not XML_DTD */
|
||||
|
||||
#define XML_PROLOG_STATE 0
|
||||
#define XML_CONTENT_STATE 1
|
||||
#define XML_CDATA_SECTION_STATE 2
|
||||
#ifdef XML_DTD
|
||||
#define XML_IGNORE_SECTION_STATE 3
|
||||
#endif /* XML_DTD */
|
||||
|
||||
#define XML_N_LITERAL_TYPES 2
|
||||
#define XML_ATTRIBUTE_VALUE_LITERAL 0
|
||||
#define XML_ENTITY_VALUE_LITERAL 1
|
||||
|
||||
/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
|
||||
#define XML_UTF8_ENCODE_MAX 4
|
||||
/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
|
||||
#define XML_UTF16_ENCODE_MAX 2
|
||||
|
||||
typedef struct position {
|
||||
/* first line and first column are 0 not 1 */
|
||||
unsigned long lineNumber;
|
||||
unsigned long columnNumber;
|
||||
} POSITION;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *valuePtr;
|
||||
const char *valueEnd;
|
||||
char normalized;
|
||||
} ATTRIBUTE;
|
||||
|
||||
struct encoding;
|
||||
typedef struct encoding ENCODING;
|
||||
|
||||
struct encoding {
|
||||
int (*scanners[XML_N_STATES])(const ENCODING *,
|
||||
const char *,
|
||||
const char *,
|
||||
const char **);
|
||||
int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *,
|
||||
const char *,
|
||||
const char *,
|
||||
const char **);
|
||||
int (*sameName)(const ENCODING *,
|
||||
const char *, const char *);
|
||||
int (*nameMatchesAscii)(const ENCODING *,
|
||||
const char *, const char *, const char *);
|
||||
int (*nameLength)(const ENCODING *, const char *);
|
||||
const char *(*skipS)(const ENCODING *, const char *);
|
||||
int (*getAtts)(const ENCODING *enc, const char *ptr,
|
||||
int attsMax, ATTRIBUTE *atts);
|
||||
int (*charRefNumber)(const ENCODING *enc, const char *ptr);
|
||||
int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
|
||||
void (*updatePosition)(const ENCODING *,
|
||||
const char *ptr,
|
||||
const char *end,
|
||||
POSITION *);
|
||||
int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
|
||||
const char **badPtr);
|
||||
void (*utf8Convert)(const ENCODING *enc,
|
||||
const char **fromP,
|
||||
const char *fromLim,
|
||||
char **toP,
|
||||
const char *toLim);
|
||||
void (*utf16Convert)(const ENCODING *enc,
|
||||
const char **fromP,
|
||||
const char *fromLim,
|
||||
unsigned short **toP,
|
||||
const unsigned short *toLim);
|
||||
int minBytesPerChar;
|
||||
char isUtf8;
|
||||
char isUtf16;
|
||||
};
|
||||
|
||||
/*
|
||||
Scan the string starting at ptr until the end of the next complete token,
|
||||
but do not scan past eptr. Return an integer giving the type of token.
|
||||
|
||||
Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
|
||||
|
||||
Return XML_TOK_PARTIAL when the string does not contain a complete token;
|
||||
nextTokPtr will not be set.
|
||||
|
||||
Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr
|
||||
will be set to point to the character which made the token invalid.
|
||||
|
||||
Otherwise the string starts with a valid token; nextTokPtr will be set to point
|
||||
to the character following the end of that token.
|
||||
|
||||
Each data character counts as a single token, but adjacent data characters
|
||||
may be returned together. Similarly for characters in the prolog outside
|
||||
literals, comments and processing instructions.
|
||||
*/
|
||||
|
||||
|
||||
#define XmlTok(enc, state, ptr, end, nextTokPtr) \
|
||||
(((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
|
||||
|
||||
#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlContentTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#ifdef XML_DTD
|
||||
|
||||
#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
|
||||
|
||||
#endif /* XML_DTD */
|
||||
|
||||
/* This is used for performing a 2nd-level tokenization on
|
||||
the content of a literal that has already been returned by XmlTok. */
|
||||
|
||||
#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
|
||||
(((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
|
||||
|
||||
#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
|
||||
XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
|
||||
|
||||
#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
|
||||
|
||||
#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
|
||||
(((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
|
||||
|
||||
#define XmlNameLength(enc, ptr) \
|
||||
(((enc)->nameLength)(enc, ptr))
|
||||
|
||||
#define XmlSkipS(enc, ptr) \
|
||||
(((enc)->skipS)(enc, ptr))
|
||||
|
||||
#define XmlGetAttributes(enc, ptr, attsMax, atts) \
|
||||
(((enc)->getAtts)(enc, ptr, attsMax, atts))
|
||||
|
||||
#define XmlCharRefNumber(enc, ptr) \
|
||||
(((enc)->charRefNumber)(enc, ptr))
|
||||
|
||||
#define XmlPredefinedEntityName(enc, ptr, end) \
|
||||
(((enc)->predefinedEntityName)(enc, ptr, end))
|
||||
|
||||
#define XmlUpdatePosition(enc, ptr, end, pos) \
|
||||
(((enc)->updatePosition)(enc, ptr, end, pos))
|
||||
|
||||
#define XmlIsPublicId(enc, ptr, end, badPtr) \
|
||||
(((enc)->isPublicId)(enc, ptr, end, badPtr))
|
||||
|
||||
#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
|
||||
(((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
|
||||
|
||||
#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
|
||||
(((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
|
||||
|
||||
typedef struct {
|
||||
ENCODING initEnc;
|
||||
const ENCODING **encPtr;
|
||||
} INIT_ENCODING;
|
||||
|
||||
int XMLTOKAPI XmlParseXmlDecl(int isGeneralTextEntity,
|
||||
const ENCODING *enc,
|
||||
const char *ptr,
|
||||
const char *end,
|
||||
const char **badPtr,
|
||||
const char **versionPtr,
|
||||
const char **encodingNamePtr,
|
||||
const ENCODING **namedEncodingPtr,
|
||||
int *standalonePtr);
|
||||
|
||||
int XMLTOKAPI XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
|
||||
const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncoding(void);
|
||||
const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncoding(void);
|
||||
int XMLTOKAPI XmlUtf8Encode(int charNumber, char *buf);
|
||||
int XMLTOKAPI XmlUtf16Encode(int charNumber, unsigned short *buf);
|
||||
|
||||
int XMLTOKAPI XmlSizeOfUnknownEncoding(void);
|
||||
ENCODING XMLTOKAPI *
|
||||
XmlInitUnknownEncoding(void *mem,
|
||||
int *table,
|
||||
int (*conv)(void *userData, const char *p),
|
||||
void *userData);
|
||||
|
||||
int XMLTOKAPI XmlParseXmlDeclNS(int isGeneralTextEntity,
|
||||
const ENCODING *enc,
|
||||
const char *ptr,
|
||||
const char *end,
|
||||
const char **badPtr,
|
||||
const char **versionPtr,
|
||||
const char **encodingNamePtr,
|
||||
const ENCODING **namedEncodingPtr,
|
||||
int *standalonePtr);
|
||||
int XMLTOKAPI XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
|
||||
const ENCODING XMLTOKAPI *XmlGetUtf8InternalEncodingNS(void);
|
||||
const ENCODING XMLTOKAPI *XmlGetUtf16InternalEncodingNS(void);
|
||||
ENCODING XMLTOKAPI *
|
||||
XmlInitUnknownEncodingNS(void *mem,
|
||||
int *table,
|
||||
int (*conv)(void *userData, const char *p),
|
||||
void *userData);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* not XmlTok_INCLUDED */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
enum {
|
||||
BT_NONXML,
|
||||
BT_MALFORM,
|
||||
BT_LT,
|
||||
BT_AMP,
|
||||
BT_RSQB,
|
||||
BT_LEAD2,
|
||||
BT_LEAD3,
|
||||
BT_LEAD4,
|
||||
BT_TRAIL,
|
||||
BT_CR,
|
||||
BT_LF,
|
||||
BT_GT,
|
||||
BT_QUOT,
|
||||
BT_APOS,
|
||||
BT_EQUALS,
|
||||
BT_QUEST,
|
||||
BT_EXCL,
|
||||
BT_SOL,
|
||||
BT_SEMI,
|
||||
BT_NUM,
|
||||
BT_LSQB,
|
||||
BT_S,
|
||||
BT_NMSTRT,
|
||||
BT_COLON,
|
||||
BT_HEX,
|
||||
BT_DIGIT,
|
||||
BT_NAME,
|
||||
BT_MINUS,
|
||||
BT_OTHER, /* known not to be a name or name start character */
|
||||
BT_NONASCII, /* might be a name or name start character */
|
||||
BT_PERCNT,
|
||||
BT_LPAR,
|
||||
BT_RPAR,
|
||||
BT_AST,
|
||||
BT_PLUS,
|
||||
BT_COMMA,
|
||||
BT_VERBAR
|
||||
};
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -0,0 +1,96 @@
|
||||
const ENCODING *NS(XmlGetUtf8InternalEncoding)(void)
|
||||
{
|
||||
return &ns(internal_utf8_encoding).enc;
|
||||
}
|
||||
|
||||
const ENCODING *NS(XmlGetUtf16InternalEncoding)(void)
|
||||
{
|
||||
#if XML_BYTE_ORDER == 12
|
||||
return &ns(internal_little2_encoding).enc;
|
||||
#elif XML_BYTE_ORDER == 21
|
||||
return &ns(internal_big2_encoding).enc;
|
||||
#else
|
||||
const short n = 1;
|
||||
return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
|
||||
#endif
|
||||
}
|
||||
|
||||
static
|
||||
const ENCODING *NS(encodings)[] = {
|
||||
&ns(latin1_encoding).enc,
|
||||
&ns(ascii_encoding).enc,
|
||||
&ns(utf8_encoding).enc,
|
||||
&ns(big2_encoding).enc,
|
||||
&ns(big2_encoding).enc,
|
||||
&ns(little2_encoding).enc,
|
||||
&ns(utf8_encoding).enc /* NO_ENC */
|
||||
};
|
||||
|
||||
static
|
||||
int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
|
||||
const char **nextTokPtr)
|
||||
{
|
||||
return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
|
||||
}
|
||||
|
||||
static
|
||||
int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
|
||||
const char **nextTokPtr)
|
||||
{
|
||||
return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
|
||||
}
|
||||
|
||||
int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
|
||||
{
|
||||
int i = getEncodingIndex(name);
|
||||
if (i == UNKNOWN_ENC)
|
||||
return 0;
|
||||
SET_INIT_ENC_INDEX(p, i);
|
||||
p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
|
||||
p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
|
||||
p->initEnc.updatePosition = initUpdatePosition;
|
||||
p->encPtr = encPtr;
|
||||
*encPtr = &(p->initEnc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
|
||||
{
|
||||
#define ENCODING_MAX 128
|
||||
char buf[ENCODING_MAX];
|
||||
char *p = buf;
|
||||
int i;
|
||||
XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
|
||||
if (ptr != end)
|
||||
return 0;
|
||||
*p = 0;
|
||||
if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2)
|
||||
return enc;
|
||||
i = getEncodingIndex(buf);
|
||||
if (i == UNKNOWN_ENC)
|
||||
return 0;
|
||||
return NS(encodings)[i];
|
||||
}
|
||||
|
||||
int NS(XmlParseXmlDecl)(int isGeneralTextEntity,
|
||||
const ENCODING *enc,
|
||||
const char *ptr,
|
||||
const char *end,
|
||||
const char **badPtr,
|
||||
const char **versionPtr,
|
||||
const char **encodingName,
|
||||
const ENCODING **encoding,
|
||||
int *standalone)
|
||||
{
|
||||
return doParseXmlDecl(NS(findEncoding),
|
||||
isGeneralTextEntity,
|
||||
enc,
|
||||
ptr,
|
||||
end,
|
||||
badPtr,
|
||||
versionPtr,
|
||||
encodingName,
|
||||
encoding,
|
||||
standalone);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Makefile
|
||||
@@ -0,0 +1,209 @@
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ../../..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
ABYSS_SUBDIR = @ABYSS_SUBDIR@
|
||||
AS = @AS@
|
||||
ASYNCH_CLIENT = @ASYNCH_CLIENT@
|
||||
AUTH_CLIENT = @AUTH_CLIENT@
|
||||
AVAILABLE_MODULES = @AVAILABLE_MODULES@
|
||||
CC = @CC@
|
||||
CC_WARN_FLAGS = @CC_WARN_FLAGS@
|
||||
CLIENTTEST = @CLIENTTEST@
|
||||
CONFIGURE_DATE = @CONFIGURE_DATE@
|
||||
CPPTEST = @CPPTEST@
|
||||
CPP_WARN_FLAGS = @CPP_WARN_FLAGS@
|
||||
CXX = @CXX@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
EFRPCTEST = @EFRPCTEST@
|
||||
EFRPCTEST_WRAPPER = @EFRPCTEST_WRAPPER@
|
||||
INTEROP_CGI = @INTEROP_CGI@
|
||||
INTEROP_CLIENT_SUBDIR = @INTEROP_CLIENT_SUBDIR@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBWWW_CFLAGS = @LIBWWW_CFLAGS@
|
||||
LIBWWW_CONFIG = @LIBWWW_CONFIG@
|
||||
LIBWWW_LDADD = @LIBWWW_LDADD@
|
||||
LIBWWW_LIBDIR = @LIBWWW_LIBDIR@
|
||||
LIBWWW_RPATH = @LIBWWW_RPATH@
|
||||
LIBWWW_WL_RPATH = @LIBWWW_WL_RPATH@
|
||||
LIBXMLRPC_ABYSS_SERVER_LA = @LIBXMLRPC_ABYSS_SERVER_LA@
|
||||
LIBXMLRPC_CGI_LA = @LIBXMLRPC_CGI_LA@
|
||||
LIBXMLRPC_CLIENT_LA = @LIBXMLRPC_CLIENT_LA@
|
||||
LIBXMLRPC_CPP_A = @LIBXMLRPC_CPP_A@
|
||||
LN_S = @LN_S@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MEERKAT_APP_LIST = @MEERKAT_APP_LIST@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
PACKAGE = @PACKAGE@
|
||||
QUERY_MEERKAT = @QUERY_MEERKAT@
|
||||
RANLIB = @RANLIB@
|
||||
SAMPLE_CGI_CGI = @SAMPLE_CGI_CGI@
|
||||
SERVER = @SERVER@
|
||||
SERVERTEST = @SERVERTEST@
|
||||
SYNCH_CLIENT = @SYNCH_CLIENT@
|
||||
VALIDATEE = @VALIDATEE@
|
||||
VERSION = @VERSION@
|
||||
VERSION_INFO = @VERSION_INFO@
|
||||
XMLRPCCPP_H = @XMLRPCCPP_H@
|
||||
XMLRPC_ABYSS_H = @XMLRPC_ABYSS_H@
|
||||
XMLRPC_CGI_H = @XMLRPC_CGI_H@
|
||||
XMLRPC_CLIENT_H = @XMLRPC_CLIENT_H@
|
||||
XML_RPC_API2CPP_SUBDIR = @XML_RPC_API2CPP_SUBDIR@
|
||||
|
||||
EXTRA_DIST = codepage.c filemap.h unixfilemap.c xmlfile.c xmltchar.h xmlwf.dsp codepage.h readfilemap.c win32filemap.c xmlfile.h xmlwf.c
|
||||
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../../../xmlrpc_config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_COMMON = Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
tags: TAGS
|
||||
TAGS:
|
||||
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = lib/expat/xmlwf
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-exec-am:
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am:
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile
|
||||
all-redirect: all-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
clean: clean-am
|
||||
|
||||
distclean-am: distclean-generic clean-am
|
||||
-rm -f libtool
|
||||
|
||||
distclean: distclean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-generic distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
|
||||
installcheck-am installcheck install-exec-am install-exec \
|
||||
install-data-am install-data install-am install uninstall-am uninstall \
|
||||
all-redirect all-am all installdirs mostlyclean-generic \
|
||||
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||
mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#include "codepage.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define STRICT 1
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
int codepageMap(int cp, int *map)
|
||||
{
|
||||
int i;
|
||||
CPINFO info;
|
||||
if (!GetCPInfo(cp, &info) || info.MaxCharSize > 2)
|
||||
return 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
map[i] = -1;
|
||||
if (info.MaxCharSize > 1) {
|
||||
for (i = 0; i < MAX_LEADBYTES; i++) {
|
||||
int j, lim;
|
||||
if (info.LeadByte[i] == 0 && info.LeadByte[i + 1] == 0)
|
||||
break;
|
||||
lim = info.LeadByte[i + 1];
|
||||
for (j = info.LeadByte[i]; j < lim; j++)
|
||||
map[j] = -2;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (map[i] == -1) {
|
||||
char c = i;
|
||||
unsigned short n;
|
||||
if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
|
||||
&c, 1, &n, 1) == 1)
|
||||
map[i] = n;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int codepageConvert(int cp, const char *p)
|
||||
{
|
||||
unsigned short c;
|
||||
if (MultiByteToWideChar(cp, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
|
||||
p, 2, &c, 1) == 1)
|
||||
return c;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else /* not WIN32 */
|
||||
|
||||
int codepageMap(int cp, int *map)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int codepageConvert(int cp, const char *p)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* not WIN32 */
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
int codepageMap(int cp, int *map);
|
||||
int codepageConvert(int cp, const char *p);
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef XML_UNICODE
|
||||
int filemap(const wchar_t *name,
|
||||
void (*processor)(const void *, size_t, const wchar_t *, void *arg),
|
||||
void *arg);
|
||||
#else
|
||||
int filemap(const char *name,
|
||||
void (*processor)(const void *, size_t, const char *, void *arg),
|
||||
void *arg);
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef S_ISREG
|
||||
#ifndef S_IFREG
|
||||
#define S_IFREG _S_IFREG
|
||||
#endif
|
||||
#ifndef S_IFMT
|
||||
#define S_IFMT _S_IFMT
|
||||
#endif
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif /* not S_ISREG */
|
||||
|
||||
#ifndef O_BINARY
|
||||
#ifdef _O_BINARY
|
||||
#define O_BINARY _O_BINARY
|
||||
#else
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int filemap(const char *name,
|
||||
void (*processor)(const void *, size_t, const char *, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
size_t nbytes;
|
||||
int fd;
|
||||
int n;
|
||||
struct stat sb;
|
||||
void *p;
|
||||
|
||||
fd = open(name, O_RDONLY|O_BINARY);
|
||||
if (fd < 0) {
|
||||
perror(name);
|
||||
return 0;
|
||||
}
|
||||
if (fstat(fd, &sb) < 0) {
|
||||
perror(name);
|
||||
return 0;
|
||||
}
|
||||
if (!S_ISREG(sb.st_mode)) {
|
||||
fprintf(stderr, "%s: not a regular file\n", name);
|
||||
return 0;
|
||||
}
|
||||
nbytes = sb.st_size;
|
||||
p = malloc(nbytes);
|
||||
if (!p) {
|
||||
fprintf(stderr, "%s: out of memory\n", name);
|
||||
return 0;
|
||||
}
|
||||
n = read(fd, p, nbytes);
|
||||
if (n < 0) {
|
||||
perror(name);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (n != nbytes) {
|
||||
fprintf(stderr, "%s: read unexpected number of bytes\n", name);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
processor(p, nbytes, name, arg);
|
||||
free(p);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef MAP_FILE
|
||||
#define MAP_FILE 0
|
||||
#endif
|
||||
|
||||
#include "filemap.h"
|
||||
|
||||
int filemap(const char *name,
|
||||
void (*processor)(const void *, size_t, const char *, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
int fd;
|
||||
size_t nbytes;
|
||||
struct stat sb;
|
||||
void *p;
|
||||
|
||||
fd = open(name, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror(name);
|
||||
return 0;
|
||||
}
|
||||
if (fstat(fd, &sb) < 0) {
|
||||
perror(name);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (!S_ISREG(sb.st_mode)) {
|
||||
close(fd);
|
||||
fprintf(stderr, "%s: not a regular file\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nbytes = sb.st_size;
|
||||
p = (void *)mmap((caddr_t)0, (size_t)nbytes, PROT_READ,
|
||||
MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
|
||||
if (p == (void *)-1) {
|
||||
perror(name);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
processor(p, nbytes, name, arg);
|
||||
munmap((caddr_t)p, nbytes);
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#define STRICT 1
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
|
||||
#ifdef XML_UNICODE_WCHAR_T
|
||||
#ifndef XML_UNICODE
|
||||
#define XML_UNICODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef XML_UNICODE
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
#endif /* XML_UNICODE */
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include "filemap.h"
|
||||
|
||||
static void win32perror(const TCHAR *);
|
||||
|
||||
int filemap(const TCHAR *name,
|
||||
void (*processor)(const void *, size_t, const TCHAR *, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
HANDLE f;
|
||||
HANDLE m;
|
||||
DWORD size;
|
||||
DWORD sizeHi;
|
||||
void *p;
|
||||
|
||||
f = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||
if (f == INVALID_HANDLE_VALUE) {
|
||||
win32perror(name);
|
||||
return 0;
|
||||
}
|
||||
size = GetFileSize(f, &sizeHi);
|
||||
if (size == (DWORD)-1) {
|
||||
win32perror(name);
|
||||
return 0;
|
||||
}
|
||||
if (sizeHi) {
|
||||
_ftprintf(stderr, _T("%s: bigger than 2Gb\n"), name);
|
||||
return 0;
|
||||
}
|
||||
/* CreateFileMapping barfs on zero length files */
|
||||
if (size == 0) {
|
||||
static const char c = '\0';
|
||||
processor(&c, 0, name, arg);
|
||||
CloseHandle(f);
|
||||
return 1;
|
||||
}
|
||||
m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (m == NULL) {
|
||||
win32perror(name);
|
||||
CloseHandle(f);
|
||||
return 0;
|
||||
}
|
||||
p = MapViewOfFile(m, FILE_MAP_READ, 0, 0, 0);
|
||||
if (p == NULL) {
|
||||
win32perror(name);
|
||||
CloseHandle(m);
|
||||
CloseHandle(f);
|
||||
return 0;
|
||||
}
|
||||
processor(p, size, name, arg);
|
||||
UnmapViewOfFile(p);
|
||||
CloseHandle(m);
|
||||
CloseHandle(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void win32perror(const TCHAR *s)
|
||||
{
|
||||
LPVOID buf;
|
||||
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &buf,
|
||||
0,
|
||||
NULL)) {
|
||||
_ftprintf(stderr, _T("%s: %s"), s, buf);
|
||||
fflush(stderr);
|
||||
LocalFree(buf);
|
||||
}
|
||||
else
|
||||
_ftprintf(stderr, _T("%s: unknown Windows error\n"), s);
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "xmlparse.h"
|
||||
#include "xmlfile.h"
|
||||
#include "xmltchar.h"
|
||||
#include "filemap.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_SOURCE
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_BINARY
|
||||
#ifdef _O_BINARY
|
||||
#define O_BINARY _O_BINARY
|
||||
#else
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define READ_SIZE 16
|
||||
#else
|
||||
#define READ_SIZE (1024*8)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
XML_Parser parser;
|
||||
int *retPtr;
|
||||
} PROCESS_ARGS;
|
||||
|
||||
static
|
||||
void reportError(XML_Parser parser, const XML_Char *filename)
|
||||
{
|
||||
int code = XML_GetErrorCode(parser);
|
||||
const XML_Char *message = XML_ErrorString(code);
|
||||
if (message)
|
||||
ftprintf(stdout, T("%s:%d:%d: %s\n"),
|
||||
filename,
|
||||
XML_GetErrorLineNumber(parser),
|
||||
XML_GetErrorColumnNumber(parser),
|
||||
message);
|
||||
else
|
||||
ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code);
|
||||
}
|
||||
|
||||
static
|
||||
void processFile(const void *data,
|
||||
size_t size,
|
||||
const XML_Char *filename,
|
||||
void *args)
|
||||
{
|
||||
XML_Parser parser = ((PROCESS_ARGS *)args)->parser;
|
||||
int *retPtr = ((PROCESS_ARGS *)args)->retPtr;
|
||||
if (!XML_Parse(parser, data, size, 1)) {
|
||||
reportError(parser, filename);
|
||||
*retPtr = 0;
|
||||
}
|
||||
else
|
||||
*retPtr = 1;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
static
|
||||
int isAsciiLetter(XML_Char c)
|
||||
{
|
||||
return (T('a') <= c && c <= T('z')) || (T('A') <= c && c <= T('Z'));
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
static
|
||||
const XML_Char *resolveSystemId(const XML_Char *base, const XML_Char *systemId, XML_Char **toFree)
|
||||
{
|
||||
XML_Char *s;
|
||||
*toFree = 0;
|
||||
if (!base
|
||||
|| *systemId == T('/')
|
||||
#ifdef WIN32
|
||||
|| *systemId == T('\\')
|
||||
|| (isAsciiLetter(systemId[0]) && systemId[1] == T(':'))
|
||||
#endif
|
||||
)
|
||||
return systemId;
|
||||
*toFree = (XML_Char *)malloc((tcslen(base) + tcslen(systemId) + 2)*sizeof(XML_Char));
|
||||
if (!*toFree)
|
||||
return systemId;
|
||||
tcscpy(*toFree, base);
|
||||
s = *toFree;
|
||||
if (tcsrchr(s, T('/')))
|
||||
s = tcsrchr(s, T('/')) + 1;
|
||||
#ifdef WIN32
|
||||
if (tcsrchr(s, T('\\')))
|
||||
s = tcsrchr(s, T('\\')) + 1;
|
||||
#endif
|
||||
tcscpy(s, systemId);
|
||||
return *toFree;
|
||||
}
|
||||
|
||||
static
|
||||
int externalEntityRefFilemap(XML_Parser parser,
|
||||
const XML_Char *context,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId)
|
||||
{
|
||||
int result;
|
||||
XML_Char *s;
|
||||
const XML_Char *filename;
|
||||
XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
|
||||
PROCESS_ARGS args;
|
||||
args.retPtr = &result;
|
||||
args.parser = entParser;
|
||||
filename = resolveSystemId(base, systemId, &s);
|
||||
XML_SetBase(entParser, filename);
|
||||
if (!filemap(filename, processFile, &args))
|
||||
result = 0;
|
||||
free(s);
|
||||
XML_ParserFree(entParser);
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
int processStream(const XML_Char *filename, XML_Parser parser)
|
||||
{
|
||||
int fd = topen(filename, O_BINARY|O_RDONLY);
|
||||
if (fd < 0) {
|
||||
tperror(filename);
|
||||
return 0;
|
||||
}
|
||||
for (;;) {
|
||||
int nread;
|
||||
char *buf = XML_GetBuffer(parser, READ_SIZE);
|
||||
if (!buf) {
|
||||
close(fd);
|
||||
ftprintf(stderr, T("%s: out of memory\n"), filename);
|
||||
return 0;
|
||||
}
|
||||
nread = read(fd, buf, READ_SIZE);
|
||||
if (nread < 0) {
|
||||
tperror(filename);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (!XML_ParseBuffer(parser, nread, nread == 0)) {
|
||||
reportError(parser, filename);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (nread == 0) {
|
||||
close(fd);
|
||||
break;;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int externalEntityRefStream(XML_Parser parser,
|
||||
const XML_Char *context,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId)
|
||||
{
|
||||
XML_Char *s;
|
||||
const XML_Char *filename;
|
||||
int ret;
|
||||
XML_Parser entParser = XML_ExternalEntityParserCreate(parser, context, 0);
|
||||
filename = resolveSystemId(base, systemId, &s);
|
||||
XML_SetBase(entParser, filename);
|
||||
ret = processStream(filename, entParser);
|
||||
free(s);
|
||||
XML_ParserFree(entParser);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int XML_ProcessFile(XML_Parser parser,
|
||||
const XML_Char *filename,
|
||||
unsigned flags)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!XML_SetBase(parser, filename)) {
|
||||
ftprintf(stderr, T("%s: out of memory"), filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (flags & XML_EXTERNAL_ENTITIES)
|
||||
XML_SetExternalEntityRefHandler(parser,
|
||||
(flags & XML_MAP_FILE)
|
||||
? externalEntityRefFilemap
|
||||
: externalEntityRefStream);
|
||||
if (flags & XML_MAP_FILE) {
|
||||
PROCESS_ARGS args;
|
||||
args.retPtr = &result;
|
||||
args.parser = parser;
|
||||
if (!filemap(filename, processFile, &args))
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
result = processStream(filename, parser);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#define XML_MAP_FILE 01
|
||||
#define XML_EXTERNAL_ENTITIES 02
|
||||
|
||||
extern int XML_ProcessFile(XML_Parser parser,
|
||||
const XML_Char *filename,
|
||||
unsigned flags);
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifdef XML_UNICODE
|
||||
#ifndef XML_UNICODE_WCHAR_T
|
||||
#error xmlwf requires a 16-bit Unicode-compatible wchar_t
|
||||
#endif
|
||||
#define T(x) L ## x
|
||||
#define ftprintf fwprintf
|
||||
#define tfopen _wfopen
|
||||
#define fputts fputws
|
||||
#define puttc putwc
|
||||
#define tcscmp wcscmp
|
||||
#define tcscpy wcscpy
|
||||
#define tcscat wcscat
|
||||
#define tcschr wcschr
|
||||
#define tcsrchr wcsrchr
|
||||
#define tcslen wcslen
|
||||
#define tperror _wperror
|
||||
#define topen _wopen
|
||||
#define tmain wmain
|
||||
#define tremove _wremove
|
||||
#else /* not XML_UNICODE */
|
||||
#define T(x) x
|
||||
#define ftprintf fprintf
|
||||
#define tfopen fopen
|
||||
#define fputts fputs
|
||||
#define puttc putc
|
||||
#define tcscmp strcmp
|
||||
#define tcscpy strcpy
|
||||
#define tcscat strcat
|
||||
#define tcschr strchr
|
||||
#define tcsrchr strrchr
|
||||
#define tcslen strlen
|
||||
#define tperror perror
|
||||
#define topen open
|
||||
#define tmain main
|
||||
#define tremove remove
|
||||
#endif /* not XML_UNICODE */
|
||||
@@ -0,0 +1,766 @@
|
||||
/*
|
||||
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
|
||||
See the file copying.txt for copying permission.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xmlparse.h"
|
||||
#include "codepage.h"
|
||||
#include "xmlfile.h"
|
||||
#include "xmltchar.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
/* This ensures proper sorting. */
|
||||
|
||||
#define NSSEP T('\001')
|
||||
|
||||
static void characterData(void *userData, const XML_Char *s, int len)
|
||||
{
|
||||
FILE *fp = userData;
|
||||
for (; len > 0; --len, ++s) {
|
||||
switch (*s) {
|
||||
case T('&'):
|
||||
fputts(T("&"), fp);
|
||||
break;
|
||||
case T('<'):
|
||||
fputts(T("<"), fp);
|
||||
break;
|
||||
case T('>'):
|
||||
fputts(T(">"), fp);
|
||||
break;
|
||||
#ifdef W3C14N
|
||||
case 13:
|
||||
fputts(T("
"), fp);
|
||||
break;
|
||||
#else
|
||||
case T('"'):
|
||||
fputts(T("""), fp);
|
||||
break;
|
||||
case 9:
|
||||
case 10:
|
||||
case 13:
|
||||
ftprintf(fp, T("&#%d;"), *s);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
puttc(*s, fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void attributeValue(FILE *fp, const XML_Char *s)
|
||||
{
|
||||
puttc(T('='), fp);
|
||||
puttc(T('"'), fp);
|
||||
for (;;) {
|
||||
switch (*s) {
|
||||
case 0:
|
||||
case NSSEP:
|
||||
puttc(T('"'), fp);
|
||||
return;
|
||||
case T('&'):
|
||||
fputts(T("&"), fp);
|
||||
break;
|
||||
case T('<'):
|
||||
fputts(T("<"), fp);
|
||||
break;
|
||||
case T('"'):
|
||||
fputts(T("""), fp);
|
||||
break;
|
||||
#ifdef W3C14N
|
||||
case 9:
|
||||
fputts(T("	"), fp);
|
||||
break;
|
||||
case 10:
|
||||
fputts(T("
"), fp);
|
||||
break;
|
||||
case 13:
|
||||
fputts(T("
"), fp);
|
||||
break;
|
||||
#else
|
||||
case T('>'):
|
||||
fputts(T(">"), fp);
|
||||
break;
|
||||
case 9:
|
||||
case 10:
|
||||
case 13:
|
||||
ftprintf(fp, T("&#%d;"), *s);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
puttc(*s, fp);
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lexicographically comparing UTF-8 encoded attribute values,
|
||||
is equivalent to lexicographically comparing based on the character number. */
|
||||
|
||||
static int attcmp(const void *att1, const void *att2)
|
||||
{
|
||||
return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
|
||||
}
|
||||
|
||||
static void startElement(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
int nAtts;
|
||||
const XML_Char **p;
|
||||
FILE *fp = userData;
|
||||
puttc(T('<'), fp);
|
||||
fputts(name, fp);
|
||||
|
||||
p = atts;
|
||||
while (*p)
|
||||
++p;
|
||||
nAtts = (p - atts) >> 1;
|
||||
if (nAtts > 1)
|
||||
qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
|
||||
while (*atts) {
|
||||
puttc(T(' '), fp);
|
||||
fputts(*atts++, fp);
|
||||
attributeValue(fp, *atts);
|
||||
atts++;
|
||||
}
|
||||
puttc(T('>'), fp);
|
||||
}
|
||||
|
||||
static void endElement(void *userData, const XML_Char *name)
|
||||
{
|
||||
FILE *fp = userData;
|
||||
puttc(T('<'), fp);
|
||||
puttc(T('/'), fp);
|
||||
fputts(name, fp);
|
||||
puttc(T('>'), fp);
|
||||
}
|
||||
|
||||
static int nsattcmp(const void *p1, const void *p2)
|
||||
{
|
||||
const XML_Char *att1 = *(const XML_Char **)p1;
|
||||
const XML_Char *att2 = *(const XML_Char **)p2;
|
||||
int sep1 = (tcsrchr(att1, NSSEP) != 0);
|
||||
int sep2 = (tcsrchr(att1, NSSEP) != 0);
|
||||
if (sep1 != sep2)
|
||||
return sep1 - sep2;
|
||||
return tcscmp(att1, att2);
|
||||
}
|
||||
|
||||
static void startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
int nAtts;
|
||||
int nsi;
|
||||
const XML_Char **p;
|
||||
FILE *fp = userData;
|
||||
const XML_Char *sep;
|
||||
puttc(T('<'), fp);
|
||||
|
||||
sep = tcsrchr(name, NSSEP);
|
||||
if (sep) {
|
||||
fputts(T("n1:"), fp);
|
||||
fputts(sep + 1, fp);
|
||||
fputts(T(" xmlns:n1"), fp);
|
||||
attributeValue(fp, name);
|
||||
nsi = 2;
|
||||
}
|
||||
else {
|
||||
fputts(name, fp);
|
||||
nsi = 1;
|
||||
}
|
||||
|
||||
p = atts;
|
||||
while (*p)
|
||||
++p;
|
||||
nAtts = (p - atts) >> 1;
|
||||
if (nAtts > 1)
|
||||
qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
|
||||
while (*atts) {
|
||||
name = *atts++;
|
||||
sep = tcsrchr(name, NSSEP);
|
||||
puttc(T(' '), fp);
|
||||
if (sep) {
|
||||
ftprintf(fp, T("n%d:"), nsi);
|
||||
fputts(sep + 1, fp);
|
||||
}
|
||||
else
|
||||
fputts(name, fp);
|
||||
attributeValue(fp, *atts);
|
||||
if (sep) {
|
||||
ftprintf(fp, T(" xmlns:n%d"), nsi++);
|
||||
attributeValue(fp, name);
|
||||
}
|
||||
atts++;
|
||||
}
|
||||
puttc(T('>'), fp);
|
||||
}
|
||||
|
||||
static void endElementNS(void *userData, const XML_Char *name)
|
||||
{
|
||||
FILE *fp = userData;
|
||||
const XML_Char *sep;
|
||||
puttc(T('<'), fp);
|
||||
puttc(T('/'), fp);
|
||||
sep = tcsrchr(name, NSSEP);
|
||||
if (sep) {
|
||||
fputts(T("n1:"), fp);
|
||||
fputts(sep + 1, fp);
|
||||
}
|
||||
else
|
||||
fputts(name, fp);
|
||||
puttc(T('>'), fp);
|
||||
}
|
||||
|
||||
#ifndef W3C14N
|
||||
|
||||
static void processingInstruction(void *userData, const XML_Char *target, const XML_Char *data)
|
||||
{
|
||||
FILE *fp = userData;
|
||||
puttc(T('<'), fp);
|
||||
puttc(T('?'), fp);
|
||||
fputts(target, fp);
|
||||
puttc(T(' '), fp);
|
||||
fputts(data, fp);
|
||||
puttc(T('?'), fp);
|
||||
puttc(T('>'), fp);
|
||||
}
|
||||
|
||||
#endif /* not W3C14N */
|
||||
|
||||
static void defaultCharacterData(XML_Parser parser, const XML_Char *s, int len)
|
||||
{
|
||||
XML_DefaultCurrent(parser);
|
||||
}
|
||||
|
||||
static void defaultStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
XML_DefaultCurrent(parser);
|
||||
}
|
||||
|
||||
static void defaultEndElement(XML_Parser parser, const XML_Char *name)
|
||||
{
|
||||
XML_DefaultCurrent(parser);
|
||||
}
|
||||
|
||||
static void defaultProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data)
|
||||
{
|
||||
XML_DefaultCurrent(parser);
|
||||
}
|
||||
|
||||
static void nopCharacterData(XML_Parser parser, const XML_Char *s, int len)
|
||||
{
|
||||
}
|
||||
|
||||
static void nopStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
}
|
||||
|
||||
static void nopEndElement(XML_Parser parser, const XML_Char *name)
|
||||
{
|
||||
}
|
||||
|
||||
static void nopProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data)
|
||||
{
|
||||
}
|
||||
|
||||
static void markup(XML_Parser parser, const XML_Char *s, int len)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
for (; len > 0; --len, ++s)
|
||||
puttc(*s, fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaLocation(XML_Parser parser)
|
||||
{
|
||||
const XML_Char *uri = XML_GetBase(parser);
|
||||
if (uri)
|
||||
ftprintf(XML_GetUserData(parser), T(" uri=\"%s\""), uri);
|
||||
ftprintf(XML_GetUserData(parser),
|
||||
T(" byte=\"%ld\" nbytes=\"%d\" line=\"%d\" col=\"%d\""),
|
||||
XML_GetCurrentByteIndex(parser),
|
||||
XML_GetCurrentByteCount(parser),
|
||||
XML_GetCurrentLineNumber(parser),
|
||||
XML_GetCurrentColumnNumber(parser));
|
||||
}
|
||||
|
||||
static
|
||||
void metaStartDocument(XML_Parser parser)
|
||||
{
|
||||
fputts(T("<document>\n"), XML_GetUserData(parser));
|
||||
}
|
||||
|
||||
static
|
||||
void metaEndDocument(XML_Parser parser)
|
||||
{
|
||||
fputts(T("</document>\n"), XML_GetUserData(parser));
|
||||
}
|
||||
|
||||
static
|
||||
void metaStartElement(XML_Parser parser, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
const XML_Char **specifiedAttsEnd
|
||||
= atts + XML_GetSpecifiedAttributeCount(parser);
|
||||
const XML_Char **idAttPtr;
|
||||
int idAttIndex = XML_GetIdAttributeIndex(parser);
|
||||
if (idAttIndex < 0)
|
||||
idAttPtr = 0;
|
||||
else
|
||||
idAttPtr = atts + idAttIndex;
|
||||
|
||||
ftprintf(fp, T("<starttag name=\"%s\""), name);
|
||||
metaLocation(parser);
|
||||
if (*atts) {
|
||||
fputts(T(">\n"), fp);
|
||||
do {
|
||||
ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
|
||||
characterData(fp, atts[1], tcslen(atts[1]));
|
||||
if (atts >= specifiedAttsEnd)
|
||||
fputts(T("\" defaulted=\"yes\"/>\n"), fp);
|
||||
else if (atts == idAttPtr)
|
||||
fputts(T("\" id=\"yes\"/>\n"), fp);
|
||||
else
|
||||
fputts(T("\"/>\n"), fp);
|
||||
} while (*(atts += 2));
|
||||
fputts(T("</starttag>\n"), fp);
|
||||
}
|
||||
else
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaEndElement(XML_Parser parser, const XML_Char *name)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
ftprintf(fp, T("<endtag name=\"%s\""), name);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaProcessingInstruction(XML_Parser parser, const XML_Char *target, const XML_Char *data)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
|
||||
characterData(fp, data, tcslen(data));
|
||||
puttc(T('"'), fp);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaComment(XML_Parser parser, const XML_Char *data)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
fputts(T("<comment data=\""), fp);
|
||||
characterData(fp, data, tcslen(data));
|
||||
puttc(T('"'), fp);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaStartCdataSection(XML_Parser parser)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
fputts(T("<startcdata"), fp);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaEndCdataSection(XML_Parser parser)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
fputts(T("<endcdata"), fp);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaCharacterData(XML_Parser parser, const XML_Char *s, int len)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
fputts(T("<chars str=\""), fp);
|
||||
characterData(fp, s, len);
|
||||
puttc(T('"'), fp);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaStartDoctypeDecl(XML_Parser parser, const XML_Char *doctypeName)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaEndDoctypeDecl(XML_Parser parser)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
fputts(T("<enddoctype"), fp);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaUnparsedEntityDecl(XML_Parser parser,
|
||||
const XML_Char *entityName,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId,
|
||||
const XML_Char *notationName)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
ftprintf(fp, T("<entity name=\"%s\""), entityName);
|
||||
if (publicId)
|
||||
ftprintf(fp, T(" public=\"%s\""), publicId);
|
||||
fputts(T(" system=\""), fp);
|
||||
characterData(fp, systemId, tcslen(systemId));
|
||||
puttc(T('"'), fp);
|
||||
ftprintf(fp, T(" notation=\"%s\""), notationName);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaNotationDecl(XML_Parser parser,
|
||||
const XML_Char *notationName,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
ftprintf(fp, T("<notation name=\"%s\""), notationName);
|
||||
if (publicId)
|
||||
ftprintf(fp, T(" public=\"%s\""), publicId);
|
||||
if (systemId) {
|
||||
fputts(T(" system=\""), fp);
|
||||
characterData(fp, systemId, tcslen(systemId));
|
||||
puttc(T('"'), fp);
|
||||
}
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void metaExternalParsedEntityDecl(XML_Parser parser,
|
||||
const XML_Char *entityName,
|
||||
const XML_Char *base,
|
||||
const XML_Char *systemId,
|
||||
const XML_Char *publicId)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
ftprintf(fp, T("<entity name=\"%s\""), entityName);
|
||||
if (publicId)
|
||||
ftprintf(fp, T(" public=\"%s\""), publicId);
|
||||
fputts(T(" system=\""), fp);
|
||||
characterData(fp, systemId, tcslen(systemId));
|
||||
puttc(T('"'), fp);
|
||||
metaLocation(parser);
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaInternalParsedEntityDecl(XML_Parser parser,
|
||||
const XML_Char *entityName,
|
||||
const XML_Char *text,
|
||||
int textLen)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
ftprintf(fp, T("<entity name=\"%s\""), entityName);
|
||||
metaLocation(parser);
|
||||
puttc(T('>'), fp);
|
||||
characterData(fp, text, textLen);
|
||||
fputts(T("</entity/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaStartNamespaceDecl(XML_Parser parser,
|
||||
const XML_Char *prefix,
|
||||
const XML_Char *uri)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
fputts(T("<startns"), fp);
|
||||
if (prefix)
|
||||
ftprintf(fp, T(" prefix=\"%s\""), prefix);
|
||||
if (uri) {
|
||||
fputts(T(" ns=\""), fp);
|
||||
characterData(fp, uri, tcslen(uri));
|
||||
fputts(T("\"/>\n"), fp);
|
||||
}
|
||||
else
|
||||
fputts(T("/>\n"), fp);
|
||||
}
|
||||
|
||||
static
|
||||
void metaEndNamespaceDecl(XML_Parser parser, const XML_Char *prefix)
|
||||
{
|
||||
FILE *fp = XML_GetUserData(parser);
|
||||
if (!prefix)
|
||||
fputts(T("<endns/>\n"), fp);
|
||||
else
|
||||
ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
|
||||
}
|
||||
|
||||
static
|
||||
int unknownEncodingConvert(void *data, const char *p)
|
||||
{
|
||||
return codepageConvert(*(int *)data, p);
|
||||
}
|
||||
|
||||
static
|
||||
int unknownEncoding(void *userData,
|
||||
const XML_Char *name,
|
||||
XML_Encoding *info)
|
||||
{
|
||||
int cp;
|
||||
static const XML_Char prefixL[] = T("windows-");
|
||||
static const XML_Char prefixU[] = T("WINDOWS-");
|
||||
int i;
|
||||
|
||||
for (i = 0; prefixU[i]; i++)
|
||||
if (name[i] != prefixU[i] && name[i] != prefixL[i])
|
||||
return 0;
|
||||
|
||||
cp = 0;
|
||||
for (; name[i]; i++) {
|
||||
static const XML_Char digits[] = T("0123456789");
|
||||
const XML_Char *s = tcschr(digits, name[i]);
|
||||
if (!s)
|
||||
return 0;
|
||||
cp *= 10;
|
||||
cp += s - digits;
|
||||
if (cp >= 0x10000)
|
||||
return 0;
|
||||
}
|
||||
if (!codepageMap(cp, info->map))
|
||||
return 0;
|
||||
info->convert = unknownEncodingConvert;
|
||||
/* We could just cast the code page integer to a void *,
|
||||
and avoid the use of release. */
|
||||
info->release = free;
|
||||
info->data = malloc(sizeof(int));
|
||||
if (!info->data)
|
||||
return 0;
|
||||
*(int *)info->data = cp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int notStandalone(void *userData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void usage(const XML_Char *prog)
|
||||
{
|
||||
ftprintf(stderr, T("usage: %s [-n] [-p] [-r] [-s] [-w] [-x] [-d output-dir] [-e encoding] file ...\n"), prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int tmain(int argc, XML_Char **argv)
|
||||
{
|
||||
int i, j;
|
||||
const XML_Char *outputDir = 0;
|
||||
const XML_Char *encoding = 0;
|
||||
unsigned processFlags = XML_MAP_FILE;
|
||||
int windowsCodePages = 0;
|
||||
int outputType = 0;
|
||||
int useNamespaces = 0;
|
||||
int requireStandalone = 0;
|
||||
int paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
|
||||
#endif
|
||||
|
||||
i = 1;
|
||||
j = 0;
|
||||
while (i < argc) {
|
||||
if (j == 0) {
|
||||
if (argv[i][0] != T('-'))
|
||||
break;
|
||||
if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
switch (argv[i][j]) {
|
||||
case T('r'):
|
||||
processFlags &= ~XML_MAP_FILE;
|
||||
j++;
|
||||
break;
|
||||
case T('s'):
|
||||
requireStandalone = 1;
|
||||
j++;
|
||||
break;
|
||||
case T('n'):
|
||||
useNamespaces = 1;
|
||||
j++;
|
||||
break;
|
||||
case T('p'):
|
||||
paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
|
||||
/* fall through */
|
||||
case T('x'):
|
||||
processFlags |= XML_EXTERNAL_ENTITIES;
|
||||
j++;
|
||||
break;
|
||||
case T('w'):
|
||||
windowsCodePages = 1;
|
||||
j++;
|
||||
break;
|
||||
case T('m'):
|
||||
outputType = 'm';
|
||||
j++;
|
||||
break;
|
||||
case T('c'):
|
||||
outputType = 'c';
|
||||
useNamespaces = 0;
|
||||
j++;
|
||||
break;
|
||||
case T('t'):
|
||||
outputType = 't';
|
||||
j++;
|
||||
break;
|
||||
case T('d'):
|
||||
if (argv[i][j + 1] == T('\0')) {
|
||||
if (++i == argc)
|
||||
usage(argv[0]);
|
||||
outputDir = argv[i];
|
||||
}
|
||||
else
|
||||
outputDir = argv[i] + j + 1;
|
||||
i++;
|
||||
j = 0;
|
||||
break;
|
||||
case T('e'):
|
||||
if (argv[i][j + 1] == T('\0')) {
|
||||
if (++i == argc)
|
||||
usage(argv[0]);
|
||||
encoding = argv[i];
|
||||
}
|
||||
else
|
||||
encoding = argv[i] + j + 1;
|
||||
i++;
|
||||
j = 0;
|
||||
break;
|
||||
case T('\0'):
|
||||
if (j > 1) {
|
||||
i++;
|
||||
j = 0;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
if (i == argc)
|
||||
usage(argv[0]);
|
||||
for (; i < argc; i++) {
|
||||
FILE *fp = 0;
|
||||
XML_Char *outName = 0;
|
||||
int result;
|
||||
XML_Parser parser;
|
||||
if (useNamespaces)
|
||||
parser = XML_ParserCreateNS(encoding, NSSEP);
|
||||
else
|
||||
parser = XML_ParserCreate(encoding);
|
||||
if (requireStandalone)
|
||||
XML_SetNotStandaloneHandler(parser, notStandalone);
|
||||
XML_SetParamEntityParsing(parser, paramEntityParsing);
|
||||
if (outputType == 't') {
|
||||
/* This is for doing timings; this gives a more realistic estimate of
|
||||
the parsing time. */
|
||||
outputDir = 0;
|
||||
XML_SetElementHandler(parser, nopStartElement, nopEndElement);
|
||||
XML_SetCharacterDataHandler(parser, nopCharacterData);
|
||||
XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
|
||||
}
|
||||
else if (outputDir) {
|
||||
const XML_Char *file = argv[i];
|
||||
if (tcsrchr(file, T('/')))
|
||||
file = tcsrchr(file, T('/')) + 1;
|
||||
#ifdef WIN32
|
||||
if (tcsrchr(file, T('\\')))
|
||||
file = tcsrchr(file, T('\\')) + 1;
|
||||
#endif
|
||||
outName = malloc((tcslen(outputDir) + tcslen(file) + 2) * sizeof(XML_Char));
|
||||
tcscpy(outName, outputDir);
|
||||
tcscat(outName, T("/"));
|
||||
tcscat(outName, file);
|
||||
fp = tfopen(outName, T("wb"));
|
||||
if (!fp) {
|
||||
tperror(outName);
|
||||
exit(1);
|
||||
}
|
||||
setvbuf(fp, NULL, _IOFBF, 16384);
|
||||
#ifdef XML_UNICODE
|
||||
puttc(0xFEFF, fp);
|
||||
#endif
|
||||
XML_SetUserData(parser, fp);
|
||||
switch (outputType) {
|
||||
case 'm':
|
||||
XML_UseParserAsHandlerArg(parser);
|
||||
XML_SetElementHandler(parser, metaStartElement, metaEndElement);
|
||||
XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
|
||||
XML_SetCommentHandler(parser, metaComment);
|
||||
XML_SetCdataSectionHandler(parser, metaStartCdataSection, metaEndCdataSection);
|
||||
XML_SetCharacterDataHandler(parser, metaCharacterData);
|
||||
XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl, metaEndDoctypeDecl);
|
||||
XML_SetUnparsedEntityDeclHandler(parser, metaUnparsedEntityDecl);
|
||||
XML_SetNotationDeclHandler(parser, metaNotationDecl);
|
||||
XML_SetExternalParsedEntityDeclHandler(parser, metaExternalParsedEntityDecl);
|
||||
XML_SetInternalParsedEntityDeclHandler(parser, metaInternalParsedEntityDecl);
|
||||
XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl, metaEndNamespaceDecl);
|
||||
metaStartDocument(parser);
|
||||
break;
|
||||
case 'c':
|
||||
XML_UseParserAsHandlerArg(parser);
|
||||
XML_SetDefaultHandler(parser, markup);
|
||||
XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
|
||||
XML_SetCharacterDataHandler(parser, defaultCharacterData);
|
||||
XML_SetProcessingInstructionHandler(parser, defaultProcessingInstruction);
|
||||
break;
|
||||
default:
|
||||
if (useNamespaces)
|
||||
XML_SetElementHandler(parser, startElementNS, endElementNS);
|
||||
else
|
||||
XML_SetElementHandler(parser, startElement, endElement);
|
||||
XML_SetCharacterDataHandler(parser, characterData);
|
||||
#ifndef W3C14N
|
||||
XML_SetProcessingInstructionHandler(parser, processingInstruction);
|
||||
#endif /* not W3C14N */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (windowsCodePages)
|
||||
XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
|
||||
result = XML_ProcessFile(parser, argv[i], processFlags);
|
||||
if (outputDir) {
|
||||
if (outputType == 'm')
|
||||
metaEndDocument(parser);
|
||||
fclose(fp);
|
||||
if (!result)
|
||||
tremove(outName);
|
||||
free(outName);
|
||||
}
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
# Microsoft Developer Studio Project File - Name="xmlwf" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=xmlwf - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "xmlwf.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "xmlwf.mak" CFG="xmlwf - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "xmlwf - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "xmlwf - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "xmlwf - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir ".\Release"
|
||||
# PROP Intermediate_Dir ".\Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "..\xmlparse" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllimport) /YX /FD /c
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 setargv.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\bin\xmlwf.exe"
|
||||
|
||||
!ELSEIF "$(CFG)" == "xmlwf - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\Debug"
|
||||
# PROP BASE Target_Dir "."
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ".\Debug"
|
||||
# PROP Intermediate_Dir ".\Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir "."
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".\xmlparse" /I "..\xmlparse" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllimport) /YX /FD /c
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x809 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
|
||||
# ADD LINK32 setargv.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\dbgbin\xmlwf.exe"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "xmlwf - Win32 Release"
|
||||
# Name "xmlwf - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\codepage.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\readfilemap.c
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\unixfilemap.c
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\win32filemap.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmlfile.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmlwf.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\codepage.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmlfile.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xmltchar.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,45 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../..
|
||||
endif
|
||||
|
||||
include $(SRCDIR)/Makefile.config
|
||||
|
||||
LIBWWW_INCLUDES := $(shell libwww-config --cflags)
|
||||
|
||||
CFLAGS = $(CFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
|
||||
LDFLAGS = -lpthread $(LADD)
|
||||
|
||||
INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include -I$(SRCDIR)/lib/util/include \
|
||||
$(LIBWWW_INCLUDES)
|
||||
|
||||
default: all
|
||||
|
||||
.PHONY: all
|
||||
all: xmlrpc_libwww_transport.lo
|
||||
|
||||
.PHONY: clean
|
||||
clean: clean-common
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean distclean-common
|
||||
|
||||
.PHONY: tags
|
||||
tags: TAGS
|
||||
|
||||
.PHONY: distdir
|
||||
distdir:
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
|
||||
.PHONY: dep
|
||||
dep: dep-common
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
include Makefile.depend
|
||||
|
||||
xmlrpc_libwww_transport.lo:%.lo:%.c
|
||||
$(LIBTOOL) --mode=compile $(CC) -c $(INCLUDES) $(CFLAGS) $<
|
||||
|
||||
|
||||
@@ -0,0 +1,920 @@
|
||||
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE. */
|
||||
|
||||
#include "xmlrpc_config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "bool.h"
|
||||
#include "mallocvar.h"
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base_int.h"
|
||||
#include "xmlrpc-c/client.h"
|
||||
#include "xmlrpc-c/client_int.h"
|
||||
|
||||
/* The libwww interface */
|
||||
|
||||
/* These headers mistakenly define the macro PACKAGE. As
|
||||
xmlrpc_config.h already defines PACKAGE according to the package we're
|
||||
actually part of, this causes a conflict. So we undef here and then
|
||||
to avoid possible problems with an incorrect PACKAGE, we undef it again
|
||||
after.
|
||||
*/
|
||||
#undef PACKAGE
|
||||
#include "WWWLib.h"
|
||||
#include "WWWHTTP.h"
|
||||
#include "WWWInit.h"
|
||||
#undef PACKAGE
|
||||
|
||||
/* Include our libwww SSL headers, if available. */
|
||||
#if HAVE_LIBWWW_SSL
|
||||
#include "WWWSSL.h"
|
||||
#endif
|
||||
|
||||
#include "xmlrpc_libwww_transport.h"
|
||||
|
||||
/* This value was discovered by Rick Blair. His efforts shaved two seconds
|
||||
** off of every request processed. Many thanks. */
|
||||
#define SMALLEST_LEGAL_LIBWWW_TIMEOUT (21)
|
||||
|
||||
#define XMLRPC_CLIENT_USE_TIMEOUT (2)
|
||||
|
||||
|
||||
struct xmlrpc_client_transport {
|
||||
int saved_flags;
|
||||
HTList *xmlrpc_conversions;
|
||||
void * cookieJarP;
|
||||
/* This is a collection of all the cookies that servers have set
|
||||
via responses to prior requests. It's not implemented today.
|
||||
*/
|
||||
bool tracingOn;
|
||||
};
|
||||
|
||||
static struct xmlrpc_client_transport clientTransport;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/*----------------------------------------------------------------------------
|
||||
This object represents one RPC.
|
||||
-----------------------------------------------------------------------------*/
|
||||
struct xmlrpc_client_transport * clientTransportP;
|
||||
|
||||
/* These fields are used when performing synchronous calls. */
|
||||
bool is_done;
|
||||
int http_status;
|
||||
|
||||
/* Low-level information used by libwww. */
|
||||
HTRequest *request;
|
||||
HTChunk *response_data;
|
||||
HTParentAnchor *source_anchor;
|
||||
HTAnchor *dest_anchor;
|
||||
|
||||
xmlrpc_transport_asynch_complete complete;
|
||||
struct xmlrpc_call_info * callInfoP;
|
||||
} rpc;
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createCookieJar(xmlrpc_env * const envP ATTR_UNUSED,
|
||||
void ** const cookieJarP ATTR_UNUSED) {
|
||||
|
||||
/* Cookies not implemented yet */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyCookieJar(void * cookieJarP ATTR_UNUSED) {
|
||||
|
||||
/* Cookies not implemented yet */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
initLibwww(const char * const appname,
|
||||
const char * const appversion) {
|
||||
|
||||
/* We initialize the library using a robot profile, because we don't
|
||||
** care about redirects or HTTP authentication, and we want to
|
||||
** reduce our application footprint as much as possible. */
|
||||
HTProfile_newRobot(appname, appversion);
|
||||
|
||||
/* Ilya Goldberg <igg@mit.edu> provided the following code to access
|
||||
** SSL-protected servers. */
|
||||
#if HAVE_LIBWWW_SSL
|
||||
/* Set the SSL protocol method. By default, it is the highest
|
||||
** available protocol. Setting it up to SSL_V23 allows the client
|
||||
** to negotiate with the server and set up either TSLv1, SSLv3,
|
||||
** or SSLv2 */
|
||||
HTSSL_protMethod_set(HTSSL_V23);
|
||||
|
||||
/* Set the certificate verification depth to 2 in order to be able to
|
||||
** validate self-signed certificates */
|
||||
HTSSL_verifyDepth_set(2);
|
||||
|
||||
/* Register SSL stuff for handling ssl access. The parameter we pass
|
||||
** is NO because we can't be pre-emptive with POST */
|
||||
HTSSLhttps_init(NO);
|
||||
#endif /* HAVE_LIBWWW_SSL */
|
||||
|
||||
/* For interoperability with Frontier, we need to tell libwww *not*
|
||||
** to send 'Expect: 100-continue' headers. But if we're not sending
|
||||
** these, we shouldn't wait for them. So set our built-in delays to
|
||||
** the smallest legal values. */
|
||||
HTTP_setBodyWriteDelay (SMALLEST_LEGAL_LIBWWW_TIMEOUT,
|
||||
SMALLEST_LEGAL_LIBWWW_TIMEOUT);
|
||||
|
||||
/* We attempt to disable all of libwww's chatty, interactive
|
||||
** prompts. Let's hope this works. */
|
||||
HTAlert_setInteractive(NO);
|
||||
|
||||
/* Here are some alternate setup calls which will help greatly
|
||||
** with debugging, should the need arise.
|
||||
**
|
||||
** HTProfile_newNoCacheClient(appname, appversion);
|
||||
** HTAlert_setInteractive(YES);
|
||||
** HTPrint_setCallback(printer);
|
||||
** HTTrace_setCallback(tracer); */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
create(xmlrpc_env * const envP,
|
||||
int const flags,
|
||||
const char * const appname,
|
||||
const char * const appversion,
|
||||
const struct xmlrpc_xportparms * const transportParmsP ATTR_UNUSED,
|
||||
size_t const parm_size ATTR_UNUSED,
|
||||
struct xmlrpc_client_transport ** const handlePP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This does the 'create' operation for a Libwww client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
/* The Libwww transport is not re-entrant -- you can have only one
|
||||
per program instance. Even if we changed the Xmlrpc-c code not
|
||||
to use global variables, that wouldn't help because Libwww
|
||||
itself is not re-entrant.
|
||||
|
||||
So we use a global variable ('clientTransport') for our transport state.
|
||||
*/
|
||||
struct xmlrpc_client_transport * const clientTransportP = &clientTransport;
|
||||
*handlePP = clientTransportP;
|
||||
|
||||
clientTransportP->saved_flags = flags;
|
||||
|
||||
createCookieJar(envP, &clientTransportP->cookieJarP);
|
||||
if (!envP->fault_occurred) {
|
||||
if (!(clientTransportP->saved_flags &
|
||||
XMLRPC_CLIENT_SKIP_LIBWWW_INIT))
|
||||
initLibwww(appname, appversion);
|
||||
|
||||
/* Set up our list of conversions for XML-RPC requests. This is a
|
||||
** massively stripped-down version of the list in libwww's HTInit.c.
|
||||
** XXX - This is hackish; 10.0 is an arbitrary, large quality factor
|
||||
** designed to override the built-in converter for XML. */
|
||||
clientTransportP->xmlrpc_conversions = HTList_new();
|
||||
HTConversion_add(clientTransportP->xmlrpc_conversions,
|
||||
"text/xml", "*/*",
|
||||
HTThroughLine, 10.0, 0.0, 0.0);
|
||||
|
||||
if (envP->fault_occurred)
|
||||
destroyCookieJar(clientTransportP->cookieJarP);
|
||||
}
|
||||
if (getenv("XMLRPC_LIBWWW_TRACE"))
|
||||
clientTransportP->tracingOn = TRUE;
|
||||
else
|
||||
clientTransportP->tracingOn = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroy(struct xmlrpc_client_transport * const clientTransportP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This does the 'destroy' operation for a Libwww client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
XMLRPC_ASSERT(clientTransportP != NULL);
|
||||
|
||||
if (!(clientTransportP->saved_flags & XMLRPC_CLIENT_SKIP_LIBWWW_INIT)) {
|
||||
HTProfile_delete();
|
||||
}
|
||||
destroyCookieJar(clientTransportP->cookieJarP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
** HTTP Error Reporting
|
||||
**=======================================================================*/
|
||||
|
||||
static void
|
||||
set_fault_from_http_request(xmlrpc_env * const envP,
|
||||
int const status,
|
||||
HTRequest * const requestP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Assuming 'requestP' identifies a completed libwww HTTP request, set
|
||||
*envP according to its success/error status.
|
||||
-----------------------------------------------------------------------------*/
|
||||
XMLRPC_ASSERT_PTR_OK(requestP);
|
||||
|
||||
if (status == 200) {
|
||||
/* No error. Don't set one in *envP */
|
||||
} else {
|
||||
/* Get an error message from libwww. The middle three
|
||||
parameters to HTDialog_errorMessage appear to be ignored.
|
||||
XXX - The documentation for this API is terrible, so we may
|
||||
be using it incorrectly.
|
||||
*/
|
||||
HTList * const errStack = HTRequest_error(requestP);
|
||||
|
||||
if (errStack == NULL) {
|
||||
/* I think this is probably impossible, because we didn't get
|
||||
status 200, but I don't completely understand HTTP and libwww.
|
||||
*/
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_NETWORK_ERROR,
|
||||
"HTTP error #%d occurred, but there was no additional "
|
||||
"error information supplied", status);
|
||||
} else {
|
||||
const char * const msg =
|
||||
HTDialog_errorMessage(requestP, HT_A_MESSAGE, HT_MSG_NULL,
|
||||
"An error occurred", errStack);
|
||||
|
||||
if (msg == NULL)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_NETWORK_ERROR,
|
||||
"HTTP error #%d occurred. Libwww's "
|
||||
"HTDialog_errorMessage() routine was mysteriously "
|
||||
"unable to interpret the additional error information, "
|
||||
"so we have none to report.", status);
|
||||
else {
|
||||
/* Set our fault. Note that this may inlcude line breaks,
|
||||
because 'msg' may. We should fix that. Formatting for
|
||||
display is none of our business at this level.
|
||||
*/
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_NETWORK_ERROR,
|
||||
"HTTP error #%d occurred. libwww says %s", status, msg);
|
||||
|
||||
xmlrpc_strfree(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static BOOL
|
||||
setCookie(HTRequest * const request,
|
||||
HTCookie * const cookieP ATTR_UNUSED,
|
||||
void * const param ATTR_UNUSED) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is the callback from libwww to tell us the server (according to
|
||||
its response) wants us to store a cookie (and include it in future
|
||||
requests).
|
||||
|
||||
We assume that the cookies "domain" is the server's host name
|
||||
(there are options on the libwww connection to make libwww call this
|
||||
callback only when that's the case).
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpc * const rpcP = HTRequest_context(request);
|
||||
struct xmlrpc_client_transport * const clientTransportP =
|
||||
rpcP->clientTransportP;
|
||||
|
||||
BOOL retval;
|
||||
|
||||
/* Avoid unused variable warning */
|
||||
if (clientTransportP->cookieJarP == clientTransportP->cookieJarP) {}
|
||||
/* Cookies are not implemented today */
|
||||
retval = NO;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static HTAssocList *
|
||||
cookiesForHost(const char * const host ATTR_UNUSED,
|
||||
void * const cookieJarP ATTR_UNUSED) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Find and return all the cookies in jar 'cookieJarP' that are for the
|
||||
host 'host'.
|
||||
-----------------------------------------------------------------------------*/
|
||||
HTAssocList * hisCookiesP;
|
||||
|
||||
hisCookiesP = HTAssocList_new();
|
||||
|
||||
if (hisCookiesP) {
|
||||
/* Cookies are not implemented yet */
|
||||
/* Library/Examples/cookie.c in the w3c-libwww source tree contains
|
||||
an example of constructing the cookie list we are supposed to
|
||||
return. But today, we return an empty list.
|
||||
*/
|
||||
}
|
||||
return hisCookiesP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static HTAssocList *
|
||||
findCookie(HTRequest * const request,
|
||||
void * const param ATTR_UNUSED) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is the callback from libwww to get the cookies to include in a
|
||||
request (presumably values the server set via a prior response).
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpc * const rpcP = HTRequest_context(request);
|
||||
struct xmlrpc_client_transport * const clientTransportP =
|
||||
rpcP->clientTransportP;
|
||||
const char * const addr =
|
||||
HTAnchor_address((HTAnchor *) HTRequest_anchor(request));
|
||||
const char * const host = HTParse(addr, "", PARSE_HOST);
|
||||
|
||||
return cookiesForHost(host, clientTransportP->cookieJarP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
deleteSourceAnchor(HTParentAnchor * const anchor) {
|
||||
|
||||
/* We need to clear the document first, or else libwww won't
|
||||
** really delete the anchor. */
|
||||
HTAnchor_setDocument(anchor, NULL);
|
||||
|
||||
/* XXX - Deleting this anchor causes HTLibTerminate to dump core. */
|
||||
/* HTAnchor_delete(anchor); */
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createSourceAnchor(xmlrpc_env * const envP,
|
||||
HTParentAnchor ** const sourceAnchorPP,
|
||||
xmlrpc_mem_block * const xmlP) {
|
||||
|
||||
HTParentAnchor * const sourceAnchorP = HTTmpAnchor(NULL);
|
||||
|
||||
if (sourceAnchorP == NULL)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Unable to build source anchor. HTTmpAnchor() failed.");
|
||||
else {
|
||||
HTAnchor_setDocument(sourceAnchorP,
|
||||
XMLRPC_MEMBLOCK_CONTENTS(char, xmlP));
|
||||
HTAnchor_setFormat(sourceAnchorP, HTAtom_for("text/xml"));
|
||||
HTAnchor_setLength(sourceAnchorP, XMLRPC_MEMBLOCK_SIZE(char, xmlP));
|
||||
|
||||
*sourceAnchorPP = sourceAnchorP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
createDestAnchor(xmlrpc_env * const envP,
|
||||
HTAnchor ** const destAnchorPP,
|
||||
const xmlrpc_server_info * const serverP) {
|
||||
|
||||
*destAnchorPP = HTAnchor_findAddress(serverP->_server_url);
|
||||
|
||||
if (*destAnchorPP == NULL)
|
||||
xmlrpc_env_set_fault_formatted(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Could not build destination anchor. HTAnchor_findAddress() "
|
||||
"failed.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
rpcCreate(xmlrpc_env * const envP,
|
||||
struct xmlrpc_client_transport * const clientTransportP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
xmlrpc_mem_block * const xmlP,
|
||||
xmlrpc_transport_asynch_complete complete,
|
||||
struct xmlrpc_call_info * const callInfoP,
|
||||
rpc ** const rpcPP) {
|
||||
|
||||
rpc *rpcP;
|
||||
HTRqHd request_headers;
|
||||
HTStream *target_stream;
|
||||
|
||||
/* Allocate our structure. */
|
||||
MALLOCVAR(rpcP);
|
||||
XMLRPC_FAIL_IF_NULL(rpcP, envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Out of memory in rpcCreate()");
|
||||
|
||||
/* Set up our basic members. */
|
||||
rpcP->clientTransportP = clientTransportP;
|
||||
rpcP->is_done = FALSE;
|
||||
rpcP->http_status = 0;
|
||||
rpcP->complete = complete;
|
||||
rpcP->callInfoP = callInfoP;
|
||||
|
||||
/* Start cookie handler. */
|
||||
HTCookie_init();
|
||||
HTCookie_setCallbacks(setCookie, NULL, findCookie, NULL);
|
||||
HTCookie_setCookieMode(HT_COOKIE_ACCEPT |
|
||||
HT_COOKIE_SEND |
|
||||
HT_COOKIE_SAME_HOST);
|
||||
|
||||
/* Cookies aren't implemented today; reset. */
|
||||
HTCookie_setCookieMode(0);
|
||||
|
||||
/* Create a HTRequest object. */
|
||||
rpcP->request = HTRequest_new();
|
||||
XMLRPC_FAIL_IF_NULL(rpcP, envP, XMLRPC_INTERNAL_ERROR,
|
||||
"HTRequest_new failed");
|
||||
|
||||
/* Install ourselves as the request context. */
|
||||
HTRequest_setContext(rpcP->request, rpcP);
|
||||
|
||||
/* XXX - Disable the 'Expect:' header so we can talk to Frontier. */
|
||||
request_headers = HTRequest_rqHd(rpcP->request);
|
||||
request_headers = request_headers & ~HT_C_EXPECT;
|
||||
HTRequest_setRqHd(rpcP->request, request_headers);
|
||||
|
||||
/* Send an authorization header if we need one. */
|
||||
if (serverP->_http_basic_auth)
|
||||
HTRequest_addCredentials(rpcP->request, "Authorization",
|
||||
serverP->_http_basic_auth);
|
||||
|
||||
/* Make sure there is no XML conversion handler to steal our data.
|
||||
** The 'override' parameter is currently ignored by libwww, so our
|
||||
** list of conversions must be designed to co-exist with the built-in
|
||||
** conversions. */
|
||||
HTRequest_setConversion(rpcP->request,
|
||||
clientTransportP->xmlrpc_conversions, NO);
|
||||
|
||||
/* Set up our response buffer. */
|
||||
target_stream = HTStreamToChunk(rpcP->request, &rpcP->response_data, 0);
|
||||
XMLRPC_FAIL_IF_NULL(rpcP->response_data, envP, XMLRPC_INTERNAL_ERROR,
|
||||
"HTStreamToChunk failed");
|
||||
XMLRPC_ASSERT(target_stream != NULL);
|
||||
HTRequest_setOutputStream(rpcP->request, target_stream);
|
||||
HTRequest_setOutputFormat(rpcP->request, WWW_SOURCE);
|
||||
|
||||
createSourceAnchor(envP, &rpcP->source_anchor, xmlP);
|
||||
|
||||
if (!envP->fault_occurred) {
|
||||
createDestAnchor(envP, &rpcP->dest_anchor, serverP);
|
||||
|
||||
if (envP->fault_occurred)
|
||||
/* See below for comments about deleting the source and dest
|
||||
** anchors. This is a bit of a black art. */
|
||||
deleteSourceAnchor(rpcP->source_anchor);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (envP->fault_occurred) {
|
||||
if (rpcP) {
|
||||
if (rpcP->request)
|
||||
HTRequest_delete(rpcP->request);
|
||||
if (rpcP->response_data)
|
||||
HTChunk_delete(rpcP->response_data);
|
||||
free(rpcP);
|
||||
}
|
||||
}
|
||||
*rpcPP = rpcP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
rpcDestroy(rpc * const rpcP) {
|
||||
|
||||
XMLRPC_ASSERT_PTR_OK(rpcP);
|
||||
XMLRPC_ASSERT(rpcP->request != XMLRPC_BAD_POINTER);
|
||||
XMLRPC_ASSERT(rpcP->response_data != XMLRPC_BAD_POINTER);
|
||||
|
||||
/* Junji Kanemaru reports on 05.04.11 that with asynch calls, he
|
||||
get a segfault, and reversing the order of deleting the request
|
||||
and the response chunk buffer cured it. But we find no reason
|
||||
that should be so, so we're waiting for someone to arrive at an
|
||||
explanation before changing anything. HTRequest_delete() does
|
||||
destroy the output stream, and the output stream refers to the
|
||||
response chunk, but HTRequest_delete() explicitly refrains from
|
||||
destroying the response chunk. And the response chunk does not
|
||||
refer to the request.
|
||||
*/
|
||||
|
||||
HTRequest_delete(rpcP->request);
|
||||
rpcP->request = XMLRPC_BAD_POINTER;
|
||||
HTChunk_delete(rpcP->response_data);
|
||||
rpcP->response_data = XMLRPC_BAD_POINTER;
|
||||
|
||||
/* This anchor points to private data, so we're allowed to delete it. */
|
||||
deleteSourceAnchor(rpcP->source_anchor);
|
||||
|
||||
/* WARNING: We can't delete the destination anchor, because this points
|
||||
** to something in the outside world, and lives in a libwww hash table.
|
||||
** Under certain circumstances, this anchor may have been reissued to
|
||||
** somebody else. So over time, the anchor cache will grow. If this
|
||||
** is a problem for your application, read the documentation for
|
||||
** HTAnchor_deleteAll.
|
||||
**
|
||||
** However, we CAN check to make sure that no documents have been
|
||||
** attached to the anchor. This assertion may fail if you're using
|
||||
** libwww for something else, so please feel free to comment it out. */
|
||||
/* XMLRPC_ASSERT(HTAnchor_document(rpcP->dest_anchor) == NULL);
|
||||
*/
|
||||
|
||||
HTCookie_deleteCallbacks();
|
||||
HTCookie_terminate();
|
||||
|
||||
free(rpcP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
extract_response_chunk(xmlrpc_env * const envP,
|
||||
rpc * const rpcP,
|
||||
xmlrpc_mem_block ** const responseXmlPP) {
|
||||
|
||||
/* Check to make sure that w3c-libwww actually sent us some data.
|
||||
** XXX - This may happen if libwww is shut down prematurely, believe it
|
||||
** or not--we'll get a 200 OK and no data. Gag me with a bogus design
|
||||
** decision. This may also fail if some naughty libwww converter
|
||||
** ate our data unexpectedly. */
|
||||
if (!HTChunk_data(rpcP->response_data))
|
||||
xmlrpc_env_set_fault(envP, XMLRPC_NETWORK_ERROR,
|
||||
"w3c-libwww returned no data");
|
||||
else {
|
||||
*responseXmlPP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
|
||||
if (!envP->fault_occurred) {
|
||||
if (rpcP->clientTransportP->tracingOn) {
|
||||
fprintf(stderr, "HTTP chunk received: %u bytes: '%.*s'",
|
||||
HTChunk_size(rpcP->response_data),
|
||||
HTChunk_size(rpcP->response_data),
|
||||
HTChunk_data(rpcP->response_data));
|
||||
}
|
||||
|
||||
XMLRPC_MEMBLOCK_APPEND(char, envP, *responseXmlPP,
|
||||
HTChunk_data(rpcP->response_data),
|
||||
HTChunk_size(rpcP->response_data));
|
||||
if (envP->fault_occurred)
|
||||
XMLRPC_MEMBLOCK_FREE(char, *responseXmlPP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
synch_terminate_handler(HTRequest * const request,
|
||||
HTResponse * const response ATTR_UNUSED,
|
||||
void * const param ATTR_UNUSED,
|
||||
int const status) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a libwww request completion handler.
|
||||
|
||||
HTEventList_newLoop() calls this when it completes a request (with this
|
||||
registered as the completion handler).
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpc *rpcP;
|
||||
|
||||
rpcP = HTRequest_context(request);
|
||||
|
||||
rpcP->is_done = TRUE;
|
||||
rpcP->http_status = status;
|
||||
|
||||
HTEventList_stopLoop();
|
||||
|
||||
return HT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
call(xmlrpc_env * const envP,
|
||||
struct xmlrpc_client_transport * const clientTransportP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
xmlrpc_mem_block * const xmlP,
|
||||
xmlrpc_mem_block ** const responsePP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This does the 'call' operation for a Libwww client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpc * rpcP;
|
||||
|
||||
XMLRPC_ASSERT_ENV_OK(envP);
|
||||
XMLRPC_ASSERT_PTR_OK(serverP);
|
||||
XMLRPC_ASSERT_PTR_OK(xmlP);
|
||||
XMLRPC_ASSERT_PTR_OK(responsePP);
|
||||
|
||||
rpcCreate(envP, clientTransportP, serverP, xmlP, NULL, NULL, &rpcP);
|
||||
if (!envP->fault_occurred) {
|
||||
int ok;
|
||||
|
||||
/* Install our request handler. */
|
||||
HTRequest_addAfter(rpcP->request, &synch_terminate_handler,
|
||||
NULL, NULL, HT_ALL, HT_FILTER_LAST, NO);
|
||||
|
||||
/* Start our request running. */
|
||||
ok = HTPostAnchor(rpcP->source_anchor,
|
||||
rpcP->dest_anchor,
|
||||
rpcP->request);
|
||||
if (!ok)
|
||||
xmlrpc_env_set_fault(
|
||||
envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Libwww HTPostAnchor() failed to start POST request");
|
||||
else {
|
||||
/* Run our event-processing loop. HTEventList_newLoop()
|
||||
is what calls synch_terminate_handler(), by virtue of
|
||||
it being registered as a handler. It may return for
|
||||
other reasons than the request being complete, though.
|
||||
so we call it in a loop until synch_terminate_handler()
|
||||
really has been called.
|
||||
*/
|
||||
while (!rpcP->is_done)
|
||||
HTEventList_newLoop();
|
||||
|
||||
/* Fail if we didn't get a "200 OK" response from the server */
|
||||
if (rpcP->http_status != 200)
|
||||
set_fault_from_http_request(
|
||||
envP, rpcP->http_status,
|
||||
rpcP->request);
|
||||
else {
|
||||
/* XXX - Check to make sure response type is text/xml here. */
|
||||
|
||||
extract_response_chunk(envP, rpcP, responsePP);
|
||||
}
|
||||
}
|
||||
rpcDestroy(rpcP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
** Event Loop
|
||||
**=========================================================================
|
||||
** We manage a fair bit of internal state about our event loop. This is
|
||||
** needed to determine when (and if) we should exit the loop.
|
||||
*/
|
||||
|
||||
static int outstanding_asynch_calls = 0;
|
||||
static int event_loop_flags = 0;
|
||||
static int timer_called = 0;
|
||||
|
||||
static void
|
||||
register_asynch_call(void) {
|
||||
XMLRPC_ASSERT(outstanding_asynch_calls >= 0);
|
||||
outstanding_asynch_calls++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
unregister_asynch_call(void) {
|
||||
|
||||
XMLRPC_ASSERT(outstanding_asynch_calls > 0);
|
||||
outstanding_asynch_calls--;
|
||||
if (outstanding_asynch_calls == 0)
|
||||
HTEventList_stopLoop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
timer_callback(HTTimer * const timer ATTR_UNUSED,
|
||||
void * const user_data ATTR_UNUSED,
|
||||
HTEventType const event) {
|
||||
/*----------------------------------------------------------------------------
|
||||
A handy timer callback which cancels the running event loop.
|
||||
-----------------------------------------------------------------------------*/
|
||||
XMLRPC_ASSERT(event == HTEvent_TIMEOUT);
|
||||
timer_called = 1;
|
||||
HTEventList_stopLoop();
|
||||
|
||||
/* XXX - The meaning of this return value is undocumented, but close
|
||||
** inspection of libwww's source suggests that we want to return HT_OK. */
|
||||
return HT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
eventLoopRun(int const flags,
|
||||
xmlrpc_timeout const milliseconds) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Process all responses from outstanding requests as they come in.
|
||||
Return when there are no more outstanding responses.
|
||||
|
||||
Or, if 'flags' has the XMLRPC_CLIENT_USE_TIMEOUT flag set, return
|
||||
when 'milliseconds' milliseconds have elapsed, regardless of whether
|
||||
there are still outstanding responses.
|
||||
|
||||
The processing we do consists of telling libwww to process the
|
||||
completion of the libwww request. That normally includes calling
|
||||
the xmlrpc_libwww_transport request termination handler, because
|
||||
the submitter of the libwww request would have registered that as a
|
||||
callback.
|
||||
-----------------------------------------------------------------------------*/
|
||||
if (outstanding_asynch_calls > 0) {
|
||||
HTTimer *timer;
|
||||
|
||||
event_loop_flags = flags;
|
||||
|
||||
/* Run an appropriate event loop. The HTEeventList_newLoop()
|
||||
is what calls asynch_terminate_handler(), by virtue of it
|
||||
being registered as a handler.
|
||||
*/
|
||||
if (event_loop_flags & XMLRPC_CLIENT_USE_TIMEOUT) {
|
||||
|
||||
/* Run our event loop with a timer. Note that we need to be very
|
||||
** careful about race conditions--timers can be fired in either
|
||||
** HTimer_new or HTEventList_newLoop. And if our callback were to
|
||||
** get called before we entered the loop, we would never exit.
|
||||
** So we use a private flag of our own--we can't even rely on
|
||||
** HTTimer_hasTimerExpired, because that only checks the time,
|
||||
** not whether our callback has been run. Yuck. */
|
||||
timer_called = 0;
|
||||
timer = HTTimer_new(NULL, &timer_callback, NULL,
|
||||
milliseconds, YES, NO);
|
||||
XMLRPC_ASSERT(timer != NULL);
|
||||
if (!timer_called)
|
||||
HTEventList_newLoop();
|
||||
HTTimer_delete(timer);
|
||||
|
||||
} else {
|
||||
/* Run our event loop without a timer. */
|
||||
HTEventList_newLoop();
|
||||
}
|
||||
|
||||
/* Reset our flags, so we don't interfere with direct calls to the
|
||||
** libwww event loop functions. */
|
||||
event_loop_flags = 0;
|
||||
} else {
|
||||
/* There are *no* calls to process. This may mean that none
|
||||
of the asynch calls were ever set up, and the client's
|
||||
callbacks have already been called with an error, or that
|
||||
all outstanding calls were completed during a previous
|
||||
synchronous call.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
finishAsynch(
|
||||
struct xmlrpc_client_transport * const clientTransportP ATTR_UNUSED,
|
||||
xmlrpc_timeoutType const timeoutType,
|
||||
xmlrpc_timeout const timeout) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This does the 'finish_asynch' operation for a Libwww client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
eventLoopRun(timeoutType == timeout_yes ? XMLRPC_CLIENT_USE_TIMEOUT : 0,
|
||||
timeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
asynch_terminate_handler(HTRequest * const request,
|
||||
HTResponse * const response ATTR_UNUSED,
|
||||
void * const param ATTR_UNUSED,
|
||||
int const status) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Handle the completion of a libwww request.
|
||||
|
||||
This is the bottom half of the xmlrpc_libwww_transport asynchronous
|
||||
call dispatcher. It's what the dispatcher registers with libwww as
|
||||
a "local after filter" so that libwww calls it when a request that
|
||||
xmlrpc_libwww_transport submitted to it is complete.
|
||||
|
||||
We destroy the RPC, including the request which is our argument.
|
||||
Strange as that may seem, it is apparently legal for an after filter
|
||||
to destroy the request that was passed to it -- or not.
|
||||
-----------------------------------------------------------------------------*/
|
||||
xmlrpc_env env;
|
||||
rpc * rpcP;
|
||||
xmlrpc_mem_block * responseXmlP;
|
||||
|
||||
XMLRPC_ASSERT_PTR_OK(request);
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
rpcP = HTRequest_context(request);
|
||||
|
||||
/* Unregister this call from the event loop. Among other things, this
|
||||
** may decide to stop the event loop.
|
||||
**/
|
||||
unregister_asynch_call();
|
||||
|
||||
/* Give up if an error occurred. */
|
||||
if (status != 200)
|
||||
set_fault_from_http_request(&env, status, request);
|
||||
else {
|
||||
/* XXX - Check to make sure response type is text/xml here. */
|
||||
extract_response_chunk(&env, rpcP, &responseXmlP);
|
||||
}
|
||||
rpcP->complete(rpcP->callInfoP, responseXmlP, env);
|
||||
|
||||
if (!env.fault_occurred)
|
||||
XMLRPC_MEMBLOCK_FREE(char, responseXmlP);
|
||||
|
||||
rpcDestroy(rpcP);
|
||||
|
||||
xmlrpc_env_clean(&env);
|
||||
return HT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
sendRequest(xmlrpc_env * const envP,
|
||||
struct xmlrpc_client_transport * const clientTransportP,
|
||||
const xmlrpc_server_info * const serverP,
|
||||
xmlrpc_mem_block * const xmlP,
|
||||
xmlrpc_transport_asynch_complete complete,
|
||||
struct xmlrpc_call_info * const callInfoP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Initiate an XML-RPC rpc asynchronously. Don't wait for it to go to
|
||||
the server.
|
||||
|
||||
Unless we return failure, we arrange to have complete() called when
|
||||
the rpc completes.
|
||||
|
||||
This does the 'send_request' operation for a Libwww client transport.
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpc * rpcP;
|
||||
|
||||
XMLRPC_ASSERT_PTR_OK(envP);
|
||||
XMLRPC_ASSERT_PTR_OK(serverP);
|
||||
XMLRPC_ASSERT_PTR_OK(xmlP);
|
||||
XMLRPC_ASSERT_PTR_OK(callInfoP);
|
||||
|
||||
rpcCreate(envP, clientTransportP, serverP, xmlP, complete, callInfoP,
|
||||
&rpcP);
|
||||
if (!envP->fault_occurred) {
|
||||
int ok;
|
||||
|
||||
/* Install our request handler. */
|
||||
HTRequest_addAfter(rpcP->request, &asynch_terminate_handler,
|
||||
NULL, NULL, HT_ALL, HT_FILTER_LAST, NO);
|
||||
|
||||
/* Register our asynchronous call with the event loop. This means
|
||||
the user's callback is guaranteed to be called eventually.
|
||||
*/
|
||||
register_asynch_call();
|
||||
|
||||
/* This makes the TCP connection and sends the XML to the server
|
||||
as an HTTP POST request.
|
||||
|
||||
There was a comment here that said this might return failure
|
||||
(!ok) and still invoke our completion handler
|
||||
(asynch_terminate_handler(). The code attempted to deal with
|
||||
that. Well, it's impossible to deal with that, so if it really
|
||||
happens, we must fix Libwww. -Bryan 04.11.23.
|
||||
*/
|
||||
|
||||
ok = HTPostAnchor(rpcP->source_anchor,
|
||||
rpcP->dest_anchor,
|
||||
rpcP->request);
|
||||
if (!ok) {
|
||||
unregister_asynch_call();
|
||||
xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Libwww (HTPostAnchor()) failed to start the "
|
||||
"POST request.");
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
rpcDestroy(rpcP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops = {
|
||||
&create,
|
||||
&destroy,
|
||||
&sendRequest,
|
||||
&call,
|
||||
&finishAsynch,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef XMLRPC_LIBWWW_TRANSPORT_H
|
||||
#define XMLRPC_LIBWWW_TRANSPORT_H
|
||||
|
||||
#include "xmlrpc-c/transport.h"
|
||||
|
||||
extern struct xmlrpc_client_transport_ops xmlrpc_libwww_transport_ops;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../..
|
||||
BUILDDIR = $(SRCDIR)
|
||||
endif
|
||||
|
||||
default: all
|
||||
|
||||
include $(BUILDDIR)/Makefile.config
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
.PHONY: all
|
||||
all: casprintf.lo cmdline_parser.lo getoptx.lo
|
||||
|
||||
INCLUDES = -Iinclude -I$(BUILDDIR)
|
||||
|
||||
CFLAGS = $(CFLAGS_COMMON) $(INCLUDES) $(CFLAGS_PERSONAL) $(CADD)
|
||||
|
||||
%.lo:%.c
|
||||
$(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $<
|
||||
|
||||
include Makefile.depend
|
||||
|
||||
.PHONY: clean distclean
|
||||
clean: clean-common
|
||||
|
||||
distclean: clean distclean-common
|
||||
|
||||
.PHONY: dep
|
||||
dep: dep-common
|
||||
|
||||
install:
|
||||
@@ -0,0 +1,83 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */
|
||||
#include "casprintf.h"
|
||||
|
||||
|
||||
|
||||
static __inline__ void
|
||||
simpleVasprintf(char ** const retvalP,
|
||||
const char * const fmt,
|
||||
va_list varargs) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a poor man's implementation of vasprintf(), of GNU fame.
|
||||
-----------------------------------------------------------------------------*/
|
||||
size_t const initialSize = 4096;
|
||||
char * result;
|
||||
|
||||
result = malloc(initialSize);
|
||||
if (result != NULL) {
|
||||
size_t bytesNeeded;
|
||||
bytesNeeded = vsnprintf(result, initialSize, fmt, varargs);
|
||||
if (bytesNeeded > initialSize) {
|
||||
free(result);
|
||||
result = malloc(bytesNeeded);
|
||||
if (result != NULL)
|
||||
vsnprintf(result, bytesNeeded, fmt, varargs);
|
||||
} else if (bytesNeeded == initialSize) {
|
||||
if (result[initialSize-1] != '\0') {
|
||||
/* This is one of those old systems where vsnprintf()
|
||||
returns the number of bytes it used, instead of the
|
||||
number that it needed, and it in fact needed more than
|
||||
we gave it. Rather than mess with this highly unlikely
|
||||
case (old system and string > 4095 characters), we just
|
||||
treat this like an out of memory failure.
|
||||
*/
|
||||
free(result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
*retvalP = result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cvasprintf(const char ** const retvalP,
|
||||
const char * const fmt,
|
||||
va_list varargs) {
|
||||
|
||||
char * retval;
|
||||
|
||||
#if HAVE_ASPRINTF
|
||||
vasprintf(&retval, fmt, varargs);
|
||||
#else
|
||||
simpleVasprintf(&retval, fmt, varargs);
|
||||
#endif
|
||||
|
||||
*retvalP = retval;
|
||||
}
|
||||
|
||||
|
||||
void GNU_PRINTF_ATTR(2,3)
|
||||
casprintf(const char ** const retvalP, const char * const fmt, ...) {
|
||||
|
||||
va_list varargs; /* mysterious structure used by variable arg facility */
|
||||
|
||||
va_start(varargs, fmt); /* start up the mysterious variable arg facility */
|
||||
|
||||
cvasprintf(retvalP, fmt, varargs);
|
||||
|
||||
va_end(varargs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
strfree(const char * const string) {
|
||||
free((void *)string);
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
#include "xmlrpc_config.h" /* prereq for mallocvar.h -- defines __inline__ */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "mallocvar.h"
|
||||
#include "bool.h"
|
||||
#include "casprintf.h"
|
||||
#include "getoptx.h"
|
||||
|
||||
#include "cmdline_parser.h"
|
||||
|
||||
#define MAXOPTS 100
|
||||
|
||||
struct optionDesc {
|
||||
const char * name;
|
||||
enum optiontype type;
|
||||
bool present;
|
||||
union {
|
||||
unsigned int u;
|
||||
int i;
|
||||
const char * s;
|
||||
} value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct cmdlineParserCtl {
|
||||
struct optionDesc * optionDescArray;
|
||||
unsigned int numOptions;
|
||||
const char ** argumentArray;
|
||||
unsigned int numArguments;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct optionx *
|
||||
createLongOptsArray(struct optionDesc * const optionDescArray,
|
||||
unsigned int const numOptions) {
|
||||
|
||||
struct optionx * longopts;
|
||||
|
||||
MALLOCARRAY(longopts, numOptions+1);
|
||||
if (longopts != NULL) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < numOptions; ++i) {
|
||||
longopts[i].name = optionDescArray[i].name;
|
||||
/* If the option takes a value, we say it is optional even
|
||||
though it never is. That's because if we say it is
|
||||
mandatory, getopt_long_only() pretends it doesn't even
|
||||
recognize the option if the user doesn't give a value.
|
||||
We prefer to generate a meaningful error message when
|
||||
the user omits a required option value.
|
||||
*/
|
||||
longopts[i].has_arg =
|
||||
optionDescArray[i].type == OPTTYPE_FLAG ?
|
||||
no_argument : optional_argument;
|
||||
longopts[i].flag = NULL;
|
||||
longopts[i].val = i;
|
||||
}
|
||||
longopts[numOptions].name = 0;
|
||||
longopts[numOptions].has_arg = 0;
|
||||
longopts[numOptions].flag = 0;
|
||||
longopts[numOptions].val = 0;
|
||||
}
|
||||
return longopts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
parseOptionValue(const char * const optarg,
|
||||
struct optionDesc * const optionP,
|
||||
const char ** const errorP) {
|
||||
|
||||
switch (optionP->type) {
|
||||
case OPTTYPE_UINT:
|
||||
case OPTTYPE_INT: {
|
||||
if (optarg == NULL)
|
||||
casprintf(errorP, "Option requires a value");
|
||||
else if (strlen(optarg) == 0)
|
||||
casprintf(errorP, "Numeric option value is null string");
|
||||
else {
|
||||
char * tailptr;
|
||||
long const longvalue = strtol(optarg, &tailptr, 10);
|
||||
if (*tailptr != '\0')
|
||||
casprintf(errorP, "Non-numeric value "
|
||||
"for numeric option value: '%s'", optarg);
|
||||
else if (errno == ERANGE || longvalue > INT_MAX)
|
||||
casprintf(errorP, "Numeric value out of range: %s", optarg);
|
||||
else {
|
||||
if (optionP->type == OPTTYPE_UINT) {
|
||||
if (longvalue < 0)
|
||||
casprintf(errorP, "Unsigned numeric value is "
|
||||
"negative: %ld", longvalue);
|
||||
else {
|
||||
*errorP = NULL;
|
||||
optionP->value.u = (unsigned int) longvalue;
|
||||
}
|
||||
} else {
|
||||
*errorP = NULL;
|
||||
optionP->value.u = (int) longvalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OPTTYPE_STRING:
|
||||
if (optarg == NULL)
|
||||
casprintf(errorP, "Option requires a value");
|
||||
else {
|
||||
*errorP = NULL;
|
||||
optionP->value.s = strdup(optarg);
|
||||
}
|
||||
break;
|
||||
case OPTTYPE_FLAG:
|
||||
*errorP = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
processOption(struct optionDesc * const optionP,
|
||||
const char * const optarg,
|
||||
const char ** const errorP) {
|
||||
|
||||
const char * error;
|
||||
|
||||
parseOptionValue(optarg, optionP, &error);
|
||||
if (error)
|
||||
casprintf(errorP, "Error in '%s' option: %s", optionP->name, error);
|
||||
else
|
||||
optionP->present = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
extractArguments(struct cmdlineParserCtl * const cpP,
|
||||
unsigned int const argc,
|
||||
const char ** const argv) {
|
||||
|
||||
cpP->numArguments = argc - getopt_argstart();
|
||||
MALLOCARRAY(cpP->argumentArray, cpP->numArguments);
|
||||
|
||||
if (cpP->argumentArray == NULL) {
|
||||
fprintf(stderr, "Unable to allocate memory for argument array\n");
|
||||
abort();
|
||||
} else {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < cpP->numArguments; ++i) {
|
||||
cpP->argumentArray[i] = strdup(argv[getopt_argstart() + i]);
|
||||
if (cpP->argumentArray[i] == NULL) {
|
||||
fprintf(stderr, "Unable to allocate memory for Argument %u\n",
|
||||
i);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cmd_processOptions(cmdlineParser const cpP,
|
||||
int const argc,
|
||||
const char ** const argv,
|
||||
const char ** const errorP) {
|
||||
|
||||
struct optionx * longopts;
|
||||
|
||||
longopts = createLongOptsArray(cpP->optionDescArray, cpP->numOptions);
|
||||
|
||||
if (longopts == NULL)
|
||||
casprintf(errorP, "Unable to get memory for longopts array");
|
||||
else {
|
||||
int endOfOptions;
|
||||
unsigned int i;
|
||||
|
||||
*errorP = NULL;
|
||||
|
||||
/* Set up initial assumption: No options present */
|
||||
|
||||
for (i = 0; i < cpP->numOptions; ++i)
|
||||
cpP->optionDescArray[i].present = FALSE;
|
||||
|
||||
endOfOptions = FALSE; /* initial value */
|
||||
|
||||
while (!endOfOptions && !*errorP) {
|
||||
int const opterr0 = 0;
|
||||
/* Don't let getopt_long_only() print an error message */
|
||||
unsigned int longoptsIndex;
|
||||
const char * unrecognizedOption;
|
||||
const char * optarg;
|
||||
|
||||
getopt_long_onlyx(argc, (char**) argv, "", longopts,
|
||||
&longoptsIndex, opterr0,
|
||||
&endOfOptions, &optarg, &unrecognizedOption);
|
||||
|
||||
if (unrecognizedOption)
|
||||
casprintf(errorP, "Unrecognized option: '%s'",
|
||||
unrecognizedOption);
|
||||
else {
|
||||
if (!endOfOptions)
|
||||
processOption(&cpP->optionDescArray[longoptsIndex], optarg,
|
||||
errorP);
|
||||
}
|
||||
}
|
||||
if (!*errorP)
|
||||
extractArguments(cpP, argc, argv);
|
||||
|
||||
free(longopts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
cmdlineParser
|
||||
cmd_createOptionParser(void) {
|
||||
|
||||
struct cmdlineParserCtl * cpP;
|
||||
|
||||
MALLOCVAR(cpP);
|
||||
|
||||
if (cpP != NULL) {
|
||||
struct optionDesc * optionDescArray;
|
||||
|
||||
cpP->numOptions = 0;
|
||||
MALLOCARRAY(optionDescArray, MAXOPTS);
|
||||
if (optionDescArray == NULL) {
|
||||
free(cpP);
|
||||
cpP = NULL;
|
||||
} else
|
||||
cpP->optionDescArray = optionDescArray;
|
||||
}
|
||||
return cpP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cmd_destroyOptionParser(cmdlineParser const cpP) {
|
||||
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < cpP->numOptions; ++i) {
|
||||
struct optionDesc const option = cpP->optionDescArray[i];
|
||||
if (option.type == OPTTYPE_STRING && option.present)
|
||||
strfree(option.value.s);
|
||||
strfree(option.name);
|
||||
}
|
||||
|
||||
for (i = 0; i < cpP->numArguments; ++i)
|
||||
strfree(cpP->argumentArray[i]);
|
||||
|
||||
free(cpP->optionDescArray);
|
||||
free(cpP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cmd_defineOption(cmdlineParser const cpP,
|
||||
const char * const name,
|
||||
enum optiontype const type) {
|
||||
|
||||
if (cpP->numOptions < MAXOPTS) {
|
||||
cpP->optionDescArray[cpP->numOptions].name = strdup(name);
|
||||
cpP->optionDescArray[cpP->numOptions].type = type;
|
||||
|
||||
++cpP->numOptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct optionDesc *
|
||||
findOptionDesc(struct cmdlineParserCtl * const cpP,
|
||||
const char * const name) {
|
||||
|
||||
struct optionDesc * retval;
|
||||
unsigned int i;
|
||||
|
||||
retval = NULL;
|
||||
|
||||
for (i = 0; i < cpP->numOptions && !retval; ++i)
|
||||
if (strcmp(cpP->optionDescArray[i].name, name) == 0)
|
||||
retval = &cpP->optionDescArray[i];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
cmd_optionIsPresent(cmdlineParser const cpP,
|
||||
const char * const name) {
|
||||
|
||||
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
|
||||
|
||||
bool present;
|
||||
|
||||
if (!optionDescP) {
|
||||
fprintf(stderr, "cmdlineParser called incorrectly. "
|
||||
"optionIsPresent() called for undefined option '%s'\n",
|
||||
name);
|
||||
abort();
|
||||
} else
|
||||
present = optionDescP->present;
|
||||
|
||||
return present;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
cmd_getOptionValueUint(cmdlineParser const cpP,
|
||||
const char * const name) {
|
||||
|
||||
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
|
||||
|
||||
unsigned int retval;
|
||||
|
||||
if (!optionDescP) {
|
||||
fprintf(stderr, "cmdlineParser called incorrectly. "
|
||||
"cmd_getOptionValueUint() called for undefined option '%s'\n",
|
||||
name);
|
||||
abort();
|
||||
} else {
|
||||
if (optionDescP->type != OPTTYPE_UINT) {
|
||||
fprintf(stderr, "cmdlineParser called incorrectly. "
|
||||
"cmd_getOptionValueUint() called for non-unsigned integer "
|
||||
"option '%s'\n", optionDescP->name);
|
||||
abort();
|
||||
} else {
|
||||
if (optionDescP->present)
|
||||
retval = optionDescP->value.u;
|
||||
else
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
cmd_getOptionValueInt(cmdlineParser const cpP,
|
||||
const char * const name) {
|
||||
|
||||
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
|
||||
|
||||
int retval;
|
||||
|
||||
if (!optionDescP) {
|
||||
fprintf(stderr, "cmdlineParser called incorrectly. "
|
||||
"cmd_getOptionValueInt() called for undefined option '%s'\n",
|
||||
name);
|
||||
abort();
|
||||
} else {
|
||||
if (optionDescP->type != OPTTYPE_INT) {
|
||||
fprintf(stderr, "cmdlineParser called incorrectly. "
|
||||
"cmd_getOptionValueInt() called for non-integer "
|
||||
"option '%s'\n", optionDescP->name);
|
||||
abort();
|
||||
} else {
|
||||
if (optionDescP->present)
|
||||
retval = optionDescP->value.i;
|
||||
else
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
cmd_getOptionValueString(cmdlineParser const cpP,
|
||||
const char * const name) {
|
||||
|
||||
struct optionDesc * const optionDescP = findOptionDesc(cpP, name);
|
||||
|
||||
const char * retval;
|
||||
|
||||
if (!optionDescP) {
|
||||
fprintf(stderr, "cmdlineParser called incorrectly. "
|
||||
"cmd_getOptionValueString() called for "
|
||||
"undefined option '%s'\n",
|
||||
name);
|
||||
abort();
|
||||
} else {
|
||||
if (optionDescP->type != OPTTYPE_STRING) {
|
||||
fprintf(stderr, "cmdlineParser called incorrectly. "
|
||||
"getOptionValueString() called for non-string "
|
||||
"option '%s'\n", optionDescP->name);
|
||||
abort();
|
||||
} else {
|
||||
if (optionDescP->present) {
|
||||
retval = strdup(optionDescP->value.s);
|
||||
if (retval == NULL) {
|
||||
fprintf(stderr,
|
||||
"out of memory in cmd_getOptionValueString()\n");
|
||||
abort();
|
||||
}
|
||||
} else
|
||||
retval = NULL;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
cmd_argumentCount(cmdlineParser const cpP) {
|
||||
|
||||
return cpP->numArguments;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *
|
||||
cmd_getArgument(cmdlineParser const cpP,
|
||||
unsigned int const argNumber) {
|
||||
|
||||
const char * retval;
|
||||
|
||||
if (argNumber >= cpP->numArguments)
|
||||
retval = NULL;
|
||||
else {
|
||||
retval = strdup(cpP->argumentArray[argNumber]);
|
||||
|
||||
if (retval == NULL) {
|
||||
fprintf(stderr,
|
||||
"out of memory in cmd_getArgument()\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@@ -0,0 +1,462 @@
|
||||
/* This version of `getopt' appears to the caller like standard Unix getopt()
|
||||
but it behaves differently for the user, since it allows the user
|
||||
to intersperse the options with the other arguments.
|
||||
|
||||
As getopt() works, it permutes the elements of `argv' so that,
|
||||
when it is done, all the options precede everything else. Thus
|
||||
all application programs are extended to handle flexible argument order.
|
||||
|
||||
Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
|
||||
Then the behavior is completely standard.
|
||||
|
||||
GNU application programs can use a third alternative mode in which
|
||||
they can distinguish the relative order of options and other arguments.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "getoptx.h"
|
||||
|
||||
#ifdef _AIX
|
||||
#pragma alloca
|
||||
#endif
|
||||
|
||||
/* Note that on some systems, the header files above declare variables
|
||||
for use with their native getopt facilities, and those variables have
|
||||
the same names as we'd like to use. So we use things like optargx
|
||||
instead of optarg to avoid the collision.
|
||||
*/
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
*/
|
||||
static char *optargx = 0;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to getoptx().
|
||||
|
||||
On entry to getoptx(), zero means this is the first call; initialize.
|
||||
|
||||
When getoptx() returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optindx' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far.
|
||||
*/
|
||||
|
||||
static int optindx = 0;
|
||||
|
||||
/* The next char to be scanned in the option-element
|
||||
in which the last option character we returned was found.
|
||||
This allows us to pick up the scan where we left off.
|
||||
|
||||
If this is zero, or a null string, it means resume the scan
|
||||
by advancing to the next ARGV-element. */
|
||||
|
||||
static char *nextchar;
|
||||
|
||||
/* Callers store zero here to inhibit the error message
|
||||
for unrecognized options.
|
||||
*/
|
||||
|
||||
static int opterrx;
|
||||
|
||||
/* Index in _GETOPT_LONG_OPTIONS of the long-named option actually found.
|
||||
Only valid when a long-named option was found. */
|
||||
|
||||
static int option_index;
|
||||
|
||||
struct optionx * _getopt_long_options;
|
||||
|
||||
/* Handle permutation of arguments. */
|
||||
|
||||
/* Describe the part of ARGV that contains non-options that have
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first of them;
|
||||
`last_nonopt' is the index after the last of them. */
|
||||
|
||||
static int first_nonopt;
|
||||
static int last_nonopt;
|
||||
|
||||
/* Exchange two adjacent subsequences of ARGV.
|
||||
One subsequence is elements [first_nonopt,last_nonopt)
|
||||
which contains all the non-options that have been skipped so far.
|
||||
The other is elements [last_nonopt,optindx), which contains all
|
||||
the options processed since those non-options were skipped.
|
||||
|
||||
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
||||
the new indices of the non-options in ARGV after they are moved. */
|
||||
|
||||
static void
|
||||
exchange(char ** const argv) {
|
||||
unsigned int const nonopts_size =
|
||||
(last_nonopt - first_nonopt) * sizeof (char *);
|
||||
char **temp = (char **) alloca (nonopts_size);
|
||||
|
||||
/* Interchange the two blocks of data in argv. */
|
||||
|
||||
bcopy (&argv[first_nonopt], temp, nonopts_size);
|
||||
bcopy (&argv[last_nonopt], &argv[first_nonopt],
|
||||
(optindx - last_nonopt) * sizeof (char *));
|
||||
bcopy (temp, &argv[first_nonopt + optindx - last_nonopt],
|
||||
nonopts_size);
|
||||
|
||||
/* Update records for the slots the non-options now occupy. */
|
||||
|
||||
first_nonopt += (optindx - last_nonopt);
|
||||
last_nonopt = optindx;
|
||||
}
|
||||
|
||||
/* Scan elements of ARGV (whose length is ARGC) for option characters
|
||||
given in OPTSTRING.
|
||||
|
||||
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
||||
then it is an option element. The characters of this element
|
||||
(aside from the initial '-') are option characters. If getoptx()
|
||||
is called repeatedly, it returns successively each of the option characters
|
||||
from each of the option elements.
|
||||
|
||||
If getoptx() finds another option character, it returns that character,
|
||||
updating `optindx' and `nextchar' so that the next call to getoptx() can
|
||||
resume the scan with the following option character or ARGV-element.
|
||||
|
||||
If there are no more option characters, getoptx() returns `EOF'.
|
||||
Then `optindx' is the index in ARGV of the first ARGV-element
|
||||
that is not an option. (The ARGV-elements have been permuted
|
||||
so that those that are not options now come last.)
|
||||
|
||||
OPTSTRING is a string containing the legitimate option characters.
|
||||
If an option character is seen that is not listed in OPTSTRING,
|
||||
return '?' after printing an error message. If you set `opterrx' to
|
||||
zero, the error message is suppressed but we still return '?'.
|
||||
|
||||
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
||||
so the following text in the same ARGV-element, or the text of the following
|
||||
ARGV-element, is returned in `optargx'. Two colons mean an option that
|
||||
wants an optional arg; if there is text in the current ARGV-element,
|
||||
it is returned in `optargx', otherwise `optargx' is set to zero.
|
||||
|
||||
If OPTSTRING starts with `-', it requests a different method of handling the
|
||||
non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above.
|
||||
|
||||
Long-named options begin with `+' instead of `-'.
|
||||
Their names may be abbreviated as long as the abbreviation is unique
|
||||
or is an exact match for some defined option. If they have an
|
||||
argument, it follows the option name in the same ARGV-element, separated
|
||||
from the option name by a `=', or else the in next ARGV-element.
|
||||
getoptx() returns 0 when it finds a long-named option. */
|
||||
|
||||
static int
|
||||
getoptx(int const argc,
|
||||
char ** const argv,
|
||||
const char * const optstring) {
|
||||
|
||||
optargx = 0;
|
||||
|
||||
/* Initialize the internal data when the first call is made.
|
||||
Start processing options with ARGV-element 1 (since ARGV-element 0
|
||||
is the program name); the sequence of previously skipped
|
||||
non-option ARGV-elements is empty. */
|
||||
|
||||
if (optindx == 0)
|
||||
{
|
||||
first_nonopt = last_nonopt = optindx = 1;
|
||||
|
||||
nextchar = 0;
|
||||
|
||||
}
|
||||
|
||||
if (nextchar == 0 || *nextchar == 0)
|
||||
{
|
||||
/* If we have just processed some options following some non-options,
|
||||
exchange them so that the options come first. */
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optindx)
|
||||
exchange (argv);
|
||||
else if (last_nonopt != optindx)
|
||||
first_nonopt = optindx;
|
||||
|
||||
/* Now skip any additional non-options
|
||||
and extend the range of non-options previously skipped. */
|
||||
|
||||
while (optindx < argc
|
||||
&& (argv[optindx][0] != '-'|| argv[optindx][1] == 0)
|
||||
&& (argv[optindx][0] != '+'|| argv[optindx][1] == 0))
|
||||
optindx++;
|
||||
last_nonopt = optindx;
|
||||
|
||||
/* Special ARGV-element `--' means premature end of options.
|
||||
Skip it like a null option,
|
||||
then exchange with previous non-options as if it were an option,
|
||||
then skip everything else like a non-option. */
|
||||
|
||||
if (optindx != argc && !strcmp (argv[optindx], "--"))
|
||||
{
|
||||
optindx++;
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optindx)
|
||||
exchange (argv);
|
||||
else if (first_nonopt == last_nonopt)
|
||||
first_nonopt = optindx;
|
||||
last_nonopt = argc;
|
||||
|
||||
optindx = argc;
|
||||
}
|
||||
|
||||
/* If we have done all the ARGV-elements, stop the scan
|
||||
and back over any non-options that we skipped and permuted. */
|
||||
|
||||
if (optindx == argc)
|
||||
{
|
||||
/* Set the next-arg-index to point at the non-options
|
||||
that we previously skipped, so the caller will digest them. */
|
||||
if (first_nonopt != last_nonopt)
|
||||
optindx = first_nonopt;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* If we have come to a non-option and did not permute it,
|
||||
either stop the scan or describe it to the caller and pass
|
||||
it by.
|
||||
*/
|
||||
|
||||
if ((argv[optindx][0] != '-' || argv[optindx][1] == 0)
|
||||
&& (argv[optindx][0] != '+' || argv[optindx][1] == 0))
|
||||
{
|
||||
optargx = argv[optindx++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have found another option-ARGV-element.
|
||||
Start decoding its characters. */
|
||||
|
||||
nextchar = argv[optindx] + 1;
|
||||
}
|
||||
|
||||
if ((argv[optindx][0] == '+' || (argv[optindx][0] == '-'))
|
||||
)
|
||||
{
|
||||
struct optionx *p;
|
||||
char *s = nextchar;
|
||||
int exact = 0;
|
||||
int ambig = 0;
|
||||
struct optionx *pfound = 0;
|
||||
int indfound;
|
||||
|
||||
while (*s && *s != '=') s++;
|
||||
|
||||
/* Test all options for either exact match or abbreviated matches. */
|
||||
for (p = _getopt_long_options, option_index = 0; p->name;
|
||||
p++, option_index++)
|
||||
if (!strncmp (p->name, nextchar, s - nextchar))
|
||||
{
|
||||
if ((unsigned int)(s - nextchar) == strlen (p->name))
|
||||
{
|
||||
/* Exact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
exact = 1;
|
||||
break;
|
||||
}
|
||||
else if (pfound == 0)
|
||||
{
|
||||
/* First nonexact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
}
|
||||
else
|
||||
/* Second nonexact match found. */
|
||||
ambig = 1;
|
||||
}
|
||||
|
||||
if (ambig && !exact)
|
||||
{
|
||||
fprintf (stderr, "%s: option `%s' is ambiguous\n",
|
||||
argv[0], argv[optindx]);
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
|
||||
if (pfound != 0)
|
||||
{
|
||||
option_index = indfound;
|
||||
optindx++;
|
||||
if (*s)
|
||||
{
|
||||
if (pfound->has_arg > 0)
|
||||
optargx = s + 1;
|
||||
else
|
||||
{
|
||||
fprintf (stderr,
|
||||
"%s: option `%c%s' doesn't allow an argument\n",
|
||||
argv[0], argv[optindx - 1][0], pfound->name);
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
else if (pfound->has_arg)
|
||||
{
|
||||
if (optindx < argc)
|
||||
optargx = argv[optindx++];
|
||||
else if (pfound->has_arg != 2)
|
||||
{
|
||||
fprintf (stderr, "%s: option `%s' requires an argument\n",
|
||||
argv[0], argv[optindx - 1]);
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
nextchar += strlen (nextchar);
|
||||
if (pfound->flag)
|
||||
*(pfound->flag) = pfound->val;
|
||||
return 0;
|
||||
}
|
||||
if (argv[optindx][0] == '+' || index (optstring, *nextchar) == 0)
|
||||
{
|
||||
if (opterrx != 0)
|
||||
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
|
||||
argv[0], argv[optindx][0], nextchar);
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at and handle the next option-character. */
|
||||
|
||||
{
|
||||
char c = *nextchar++;
|
||||
char *temp = index (optstring, c);
|
||||
|
||||
/* Increment `optindx' when we start to process its last character. */
|
||||
if (*nextchar == 0)
|
||||
optindx++;
|
||||
|
||||
if (temp == 0 || c == ':')
|
||||
{
|
||||
if (opterrx != 0)
|
||||
{
|
||||
if (c < 040 || c >= 0177)
|
||||
fprintf (stderr, "%s: unrecognized option, "
|
||||
"character code 0%o\n",
|
||||
argv[0], c);
|
||||
else
|
||||
fprintf (stderr, "%s: unrecognized option `-%c'\n",
|
||||
argv[0], c);
|
||||
}
|
||||
return '?';
|
||||
}
|
||||
if (temp[1] == ':')
|
||||
{
|
||||
if (temp[2] == ':')
|
||||
{
|
||||
/* This is an option that accepts an argument optionally. */
|
||||
if (*nextchar != 0)
|
||||
{
|
||||
optargx = nextchar;
|
||||
optindx++;
|
||||
}
|
||||
else
|
||||
optargx = 0;
|
||||
nextchar = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an option that requires an argument. */
|
||||
if (*nextchar != 0)
|
||||
{
|
||||
optargx = nextchar;
|
||||
/* If we end this ARGV-element by taking the rest
|
||||
as an arg, we must advance to the next element
|
||||
now.
|
||||
*/
|
||||
optindx++;
|
||||
}
|
||||
else if (optindx == argc)
|
||||
{
|
||||
if (opterrx != 0)
|
||||
fprintf (stderr,
|
||||
"%s: option `-%c' requires an argument\n",
|
||||
argv[0], c);
|
||||
c = '?';
|
||||
}
|
||||
else
|
||||
/* We already incremented `optindx' once;
|
||||
increment it again when taking next ARGV-elt as
|
||||
argument.
|
||||
*/
|
||||
optargx = argv[optindx++];
|
||||
nextchar = 0;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
getopt_long_onlyx(int const argc,
|
||||
char ** const argv,
|
||||
const char * const options,
|
||||
struct optionx * const long_options,
|
||||
unsigned int * const opt_index,
|
||||
int const opterrArg,
|
||||
int * const end_of_options,
|
||||
const char ** const optarg_arg,
|
||||
const char ** const unrecognized_option) {
|
||||
|
||||
int rc;
|
||||
|
||||
opterrx = opterrArg;
|
||||
_getopt_long_options = long_options;
|
||||
rc = getoptx(argc, argv, options);
|
||||
if (rc == 0)
|
||||
*opt_index = option_index;
|
||||
|
||||
if (rc == '?')
|
||||
*unrecognized_option = argv[optindx];
|
||||
else
|
||||
*unrecognized_option = NULL;
|
||||
|
||||
if (rc < 0)
|
||||
*end_of_options = 1;
|
||||
else
|
||||
*end_of_options = 0;
|
||||
|
||||
*optarg_arg = optargx;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
getopt_argstart(void) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a replacement for what traditional getopt does with global
|
||||
variables.
|
||||
|
||||
You call this after getopt_long_onlyx() has returned "end of
|
||||
options"
|
||||
-----------------------------------------------------------------------------*/
|
||||
return optindx;
|
||||
}
|
||||
|
||||
|
||||
/* Getopt for GNU.
|
||||
Copyright (C) 1987, 1989 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Interface to getopt_long_onlyx() */
|
||||
|
||||
|
||||
enum argreq {no_argument, required_argument, optional_argument};
|
||||
|
||||
struct optionx {
|
||||
/* This describes an option. If the field `flag' is nonzero, it
|
||||
points to a variable that is to be set to the value given in
|
||||
the field `val' when the option is found, but left unchanged if
|
||||
the option is not found.
|
||||
*/
|
||||
const char * name;
|
||||
enum argreq has_arg;
|
||||
int * flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* long_options[] is a list terminated by an element that contains
|
||||
a NULL 'name' member.
|
||||
*/
|
||||
void
|
||||
getopt_long_onlyx(int const argc,
|
||||
char ** const argv,
|
||||
const char * const options,
|
||||
struct optionx * const long_options,
|
||||
unsigned int * const opt_index,
|
||||
int const opterrArg,
|
||||
int * const end_of_options,
|
||||
const char ** const optarg_arg,
|
||||
const char ** const unrecognized_option);
|
||||
|
||||
unsigned int
|
||||
getopt_argstart(void);
|
||||
|
||||
/*
|
||||
Copyright (C) 1989 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef BOOL_H_INCLUDED
|
||||
#define BOOL_H_INCLUDED
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifndef HAVE_BOOL
|
||||
#define HAVE_BOOL
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef CASPRINTF_H_INCLUDED
|
||||
#define CASPRINTF_H_INCLUDED
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* GNU_PRINTF_ATTR lets the GNU compiler check printf-type
|
||||
calls to be sure the arguments match the format string, thus preventing
|
||||
runtime segmentation faults and incorrect messages.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define GNU_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
|
||||
#else
|
||||
#define GNU_PRINTF_ATTR(a,b)
|
||||
#endif
|
||||
|
||||
void
|
||||
cvasprintf(const char ** const retvalP,
|
||||
const char * const fmt,
|
||||
va_list varargs);
|
||||
|
||||
void GNU_PRINTF_ATTR(2,3)
|
||||
casprintf(const char ** const retvalP, const char * const fmt, ...);
|
||||
|
||||
void
|
||||
strfree(const char * const string);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef CMDLINE_PARSER_H
|
||||
#define CMDLINE_PARSER_H
|
||||
|
||||
|
||||
/*
|
||||
|
||||
NOTE NOTE NOTE: cmd_getOptionValueString() and
|
||||
cmd_getArgument() return malloc'ed memory (and abort the program if
|
||||
out of memory). You must free it.
|
||||
|
||||
*/
|
||||
|
||||
enum optiontype {OPTTYPE_FLAG, OPTTYPE_INT, OPTTYPE_UINT, OPTTYPE_STRING};
|
||||
|
||||
struct cmdlineParserCtl;
|
||||
|
||||
typedef struct cmdlineParserCtl * cmdlineParser;
|
||||
|
||||
void
|
||||
cmd_processOptions(cmdlineParser const cpP,
|
||||
int const argc,
|
||||
const char ** const argv,
|
||||
const char ** const errorP);
|
||||
|
||||
cmdlineParser
|
||||
cmd_createOptionParser(void);
|
||||
|
||||
void
|
||||
cmd_destroyOptionParser(cmdlineParser const cpP);
|
||||
|
||||
void
|
||||
cmd_defineOption(cmdlineParser const cpP,
|
||||
const char * const name,
|
||||
enum optiontype const type);
|
||||
|
||||
int
|
||||
cmd_optionIsPresent(cmdlineParser const cpP,
|
||||
const char * const name);
|
||||
|
||||
unsigned int
|
||||
cmd_getOptionValueUint(cmdlineParser const cpP,
|
||||
const char * const name);
|
||||
|
||||
int
|
||||
cmd_getOptionValueInt(cmdlineParser const cpP,
|
||||
const char * const name);
|
||||
|
||||
const char *
|
||||
cmd_getOptionValueString(cmdlineParser const cpP,
|
||||
const char * const name);
|
||||
|
||||
unsigned int
|
||||
cmd_argumentCount(cmdlineParser const cpP);
|
||||
|
||||
const char *
|
||||
cmd_getArgument(cmdlineParser const cpP,
|
||||
unsigned int const argNumber);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef XMLRPC_INLINE_H_INCLUDED
|
||||
#define XMLRPC_INLINE_H_INCLUDED
|
||||
|
||||
/* Xmlrpc-c uses __inline__ to declare functions that should be
|
||||
compiled as inline code. Some compilers, e.g. GNU, recognize the
|
||||
__inline__ keyword.
|
||||
*/
|
||||
#ifndef __GNUC__
|
||||
#ifndef __inline__
|
||||
#ifdef __sgi
|
||||
#define __inline__ __inline
|
||||
#else
|
||||
#define __inline__
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
#ifndef LINKLIST_H_INCLUDED
|
||||
#define LINKLIST_H_INCLUDED
|
||||
|
||||
#include "inline.h"
|
||||
|
||||
struct list_head {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a header for an element of a doubly linked list, or an anchor
|
||||
for such a list.
|
||||
|
||||
itemP == NULL means it's an anchor; otherwise it's a header.
|
||||
|
||||
Initialize a list header with list_init_header(). You don't have to
|
||||
do anything to terminate a list header.
|
||||
|
||||
Initialize an anchor with list_make_emtpy(). You don't have to do anything
|
||||
to terminate a list header.
|
||||
-----------------------------------------------------------------------------*/
|
||||
struct list_head * nextP;
|
||||
/* For a header, this is the address of the list header for
|
||||
the next element in the list. If there is no next element,
|
||||
it points to the anchor. If the header is not in a list at
|
||||
all, it is NULL.
|
||||
|
||||
For an anchor, it is the address of the list header of the
|
||||
first element. If the list is empty, it points to the
|
||||
anchor itself.
|
||||
*/
|
||||
struct list_head * prevP;
|
||||
/* For a header, this is the address of the list header for
|
||||
the previous element in the list. If there is no previous element,
|
||||
it points to the anchor. If the header is not in a list at
|
||||
all, it is NULL.
|
||||
|
||||
For an anchor, it is the address of the list header of the
|
||||
last element. If the list is empty, it points to the
|
||||
anchor itself.
|
||||
*/
|
||||
void * itemP;
|
||||
/* For a header, this is the address of the list element to which it
|
||||
belongs. For an anchor, this is NULL.
|
||||
*/
|
||||
};
|
||||
|
||||
static __inline__ void
|
||||
list_init_header(struct list_head * const headerP,
|
||||
void * const itemP) {
|
||||
|
||||
headerP->prevP = NULL;
|
||||
headerP->nextP = NULL;
|
||||
headerP->itemP = itemP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ int
|
||||
list_is_linked(struct list_head * headerP) {
|
||||
return headerP->prevP != NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ int
|
||||
list_is_empty(struct list_head * const anchorP) {
|
||||
return anchorP->nextP == anchorP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ unsigned int
|
||||
list_count(struct list_head * const anchorP) {
|
||||
unsigned int count;
|
||||
|
||||
struct list_head * p;
|
||||
|
||||
for (p = anchorP->nextP, count = 0;
|
||||
p != anchorP;
|
||||
p = p->nextP, ++count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ void
|
||||
list_make_empty(struct list_head * const anchorP) {
|
||||
anchorP->prevP = anchorP;
|
||||
anchorP->nextP = anchorP;
|
||||
anchorP->itemP = NULL;
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
list_insert_after(struct list_head * const beforeHeaderP,
|
||||
struct list_head * const newHeaderP) {
|
||||
newHeaderP->prevP = beforeHeaderP;
|
||||
newHeaderP->nextP = beforeHeaderP->nextP;
|
||||
|
||||
beforeHeaderP->nextP = newHeaderP;
|
||||
newHeaderP->nextP->prevP = newHeaderP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ void
|
||||
list_add_tail(struct list_head * const anchorP,
|
||||
struct list_head * const headerP) {
|
||||
list_insert_after(anchorP->prevP, headerP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ void
|
||||
list_add_head(struct list_head * const anchorP,
|
||||
struct list_head * const headerP) {
|
||||
list_insert_after(anchorP, headerP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ void
|
||||
list_remove(struct list_head * const headerP) {
|
||||
headerP->prevP->nextP = headerP->nextP;
|
||||
headerP->nextP->prevP = headerP->prevP;
|
||||
headerP->prevP = NULL;
|
||||
headerP->nextP = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ struct list_head *
|
||||
list_remove_head(struct list_head * const anchorP) {
|
||||
struct list_head * retval;
|
||||
|
||||
if (list_is_empty(anchorP))
|
||||
retval = NULL;
|
||||
else {
|
||||
retval = anchorP->nextP;
|
||||
list_remove(retval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ struct list_head *
|
||||
list_remove_tail(struct list_head * const anchorP) {
|
||||
struct list_head * retval;
|
||||
|
||||
if (list_is_empty(anchorP))
|
||||
retval = NULL;
|
||||
else {
|
||||
retval = anchorP->prevP;
|
||||
list_remove(retval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ void *
|
||||
list_foreach(struct list_head * const anchorP,
|
||||
void * functionP(struct list_head *, void *),
|
||||
void * const context) {
|
||||
|
||||
struct list_head * p;
|
||||
struct list_head * nextP;
|
||||
void * result;
|
||||
|
||||
for (p = anchorP->nextP, nextP = p->nextP, result=NULL;
|
||||
p != anchorP && result == NULL;
|
||||
p = nextP, nextP = p->nextP)
|
||||
result = (*functionP)(p, context);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline__ void
|
||||
list_append(struct list_head * const newAnchorP,
|
||||
struct list_head * const baseAnchorP) {
|
||||
|
||||
if (!list_is_empty(newAnchorP)) {
|
||||
baseAnchorP->prevP->nextP = newAnchorP->nextP;
|
||||
newAnchorP->nextP->prevP = baseAnchorP->prevP;
|
||||
newAnchorP->prevP->nextP = baseAnchorP;
|
||||
baseAnchorP->prevP = newAnchorP->prevP;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user