diff -Nru serf-1.1.0/CHANGES serf-1.3.3/CHANGES --- serf-1.1.0/CHANGES 2012-06-07 20:12:29.000000000 +0000 +++ serf-1.3.3/CHANGES 2013-12-09 19:43:10.000000000 +0000 @@ -1,4 +1,113 @@ -Serf 1.1.0 [2012-06-07, from /tags/1.1.0] +Serf 1.3.3 [2013-12-09, from /tags/1.3.3, r????] + Fix issue 129: Try more addresses of multihomed servers + Handle X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE correctly (r2225) + Return APR_TIMEUP from poll() to enable detecting connection timeouts (r2183) + + +Serf 1.3.2 [2013-10-04, from /tags/1.3.2, r2195] + Fix issue 130: HTTP headers should be treated case-insensitively + Fix issue 126: Compilation breaks with Codewarrior compiler + Fix crash during cleanup of SSL buckets in apr_terminate() (r2145) + Fix Windows build: Also export functions with capital letters in .def file + Fix host header when url contains a username or password (r2170) + Ensure less TCP package fragmentation on Windows (r2145) + Handle authentication for responses to HEAD requests (r2178,-9) + Improve serf_get: add option to add request headers, allow url with query, + allow HEAD requests (r2143,r2175,-6) + Improve RFC conformance: don't expect body for certain responses (r2011,-2) + Do not invoke progress callback when no data was received (r2144) + And more test suite fixes and build warning cleanups + SCons-related fixes: + Fix build when GSSAPI not in default include path (2155) + Fix OpenBSD build: always map all LIBPATH entries into RPATH (r2156) + Checksum generation in Windows shared libraries for release builds (2162) + Mac OS X: Use MAJOR version only in dylib install name (r2161) + Use both MAJOR and MINOR version for the shared library name (2163) + Fix the .pc file when installing serf in a non-default LIBDIR (r2191) + + +Serf 1.3.1 [2013-08-15, from /tags/1.3.1, r2138] + Fix issue 77: Endless loop if server doesn't accept Negotiate authentication. + Fix issue 114: ssl/tls renegotiation fails + Fix issue 120: error with ssl tunnel over proxy with KeepAlive off and + Basic authentication. + Fixed bugs with authentication (r2057,2115,2118) + SCons-related fixes: + Fix issue 111: add flag to set custom library path + Fix issue 112: add soname + Fix issue 113: add gssapi libs in the serf pc file + Fix issue 115: Setting RPATH on Solaris broken in SConstruct + Fix issue 116: scons check should return non-zero exit staths + Fix issue 121: make CFLAGS, LIBS, LINKFLAGS and CPPFLAGS take a space- + separated list of flags. + Fix issue 122: make scons PREFIX create the folder if it doesn't exist + Mac OS X: Fix scons --install-sandbox + Solaris: Fix build with cc, don't use unsupported compiler flags + Require SCons version 2.3.0 or higher now (for the soname support). + + +Serf 1.3.0 [2013-07-23, from /tags/1.3.0, r2074] + Fix issue 83: use PATH rather than URI within an ssltunnel (r1952) + Fix issue 108: improved error reporting from the underlying socket (r1951) + NEW: Switch to the SCons build system; retire serfmake, serf.mak, autotools + Improved Basic and Digest authentication: + - remember credentials on a per-server basis + - properly manage authentication realms + - continue functioning when a server sets KeepAlive: off + Windows: add support for NTLM authentication + Improved 2617 compliance: always use strongest authentication (r1968,1971) + Fixed bugs with proxy authentication and SSL tunneling through a proxy + Fixed bugs the response parser (r2032,r2036) + SSL connection performance improvements + Huge expansion of the test suite + + +Serf 1.2.1 [2013-06-03, from /tags/1.2.1, r1906] + Fix issue 95: add gssapi switches to configure (r1864, r1900) + Fix issue 97: skip mmap bucket if APR_HAS_MMAP is undefined (r1877) + Fix issue 100: building against an old Windows Platform SDK (r1881) + Fix issue 102: digest authentication failures (r1885) + Improve error return values in SSPI authentication (r1804) + Ensure serf-1.pc is constructed by serfmake (r1865) + Optimize SPNego authentication processing (r1868) + Reject certs that application does not like (r1794) + Fix possible endless loop in serf_linebuf_fetch() (r1816) + Windows build: dereference INTDIR in serf.mak (r1882) + + +Serf 1.2.0 [2013-02-22, from /tags/1.2.0, r1726] + Fixed issue 94: Serf can enter an infinite loop when server aborts conn. + Fixed issue 91: Serf doesn't handle an incoming 408 Timeout Request + Fixed issue 80: Serf is not handling Negotiate authentication correctly + Fixed issue 77: Endless loop if server doesn't accept Negotiate authn + Fixed issue 93: cleanup-after-fork interferes with parent (r1714) + Fixed most of issue 89: Support REAL SPNEGO authentication + Enable Negotiate/Kerberos support for proxy servers. + Return error when C-L, chunked, gzip encoded response bodies were + truncated (due to aborted connection) (r1688) + Add a logging mechanism that can be enabled at compile-time. + Don't lookup server address if a proxy was configured. (r1706) + Fix an off-by-one in buffer sizing (r1695) + Disable SSL compression by default + API to enable it (r1692) + New serf_connection_get_latency() for estimated network latency (r1689) + New error code and RFC compliance for the HTTPS tunnel (r1701, r1644) + Handle EINTR when a user suspends and then backgrounds the app (r1708) + Minor fixes and test suite improvements. + + +Serf 1.1.1 [2012-10-04, from /tags/1.1.1, r1657] + Fixed issue 86: ensure requeued requests are correctly handled. + This fixes: + - infinite loop with multiple connection resets or SIGPIPE errors + - "connection" hang where we would not re-queue requests that are + held after we re-connect + Fixed issue 74: test_all goes in an endless loop + Fix memleak when conn. is closed explicitly/due to pool cleanups (r1623) + Windows: Fix https connection aborts (r1628..-30,-33,-34,-37) + Add new error codes for the SSL bucket + + +Serf 1.1.0 [2012-06-07, from /tags/1.1.0, r1617] New: serf_bucket_request_set_CL() for C-L based, non-chunked requests New: serf_ssl_server_cert_chain_callback_set() for full-chain validation diff -Nru serf-1.1.0/Makefile.in serf-1.3.3/Makefile.in --- serf-1.1.0/Makefile.in 2011-07-21 09:08:15.000000000 +0000 +++ serf-1.3.3/Makefile.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,168 +0,0 @@ -# -# Makefile for Serf -# -srcdir = @srcdir@ -VPATH = @srcdir@ - -SERF_MAJOR_VERSION=@SERF_MAJOR_VERSION@ -SERF_DOTTED_VERSION=@SERF_DOTTED_VERSION@ - -OBJECTS = buckets/aggregate_buckets.lo buckets/request_buckets.lo context.lo \ - buckets/buckets.lo buckets/simple_buckets.lo buckets/file_buckets.lo \ - buckets/mmap_buckets.lo buckets/socket_buckets.lo \ - buckets/response_buckets.lo buckets/headers_buckets.lo \ - buckets/allocator.lo buckets/dechunk_buckets.lo \ - buckets/deflate_buckets.lo buckets/limit_buckets.lo \ - buckets/ssl_buckets.lo buckets/barrier_buckets.lo \ - buckets/chunk_buckets.lo buckets/bwtp_buckets.lo \ - buckets/iovec_buckets.lo \ - incoming.lo outgoing.lo ssltunnel.lo \ - auth/auth.lo auth/auth_basic.lo auth/auth_digest.lo \ - auth/auth_kerb.lo auth/auth_kerb_gss.lo - -TARGET_LIB=libserf-$(SERF_MAJOR_VERSION).la - -TEST_OBJECTS = test/serf_get.lo test/serf_response.lo test/serf_request.lo \ - test/serf_spider.lo test/serf_server.lo test/serf_bwtp.lo - -TEST_SUITE_OBJECTS = test/CuTest.lo test/test_all.lo test/test_util.lo \ - test/test_buckets.lo test/test_context.lo \ - test/test_ssl.lo test/server/test_server.lo - -PROGRAMS = $(TEST_OBJECTS:.lo=) test/test_all - -TESTCASES = test/testcases/simple.response \ - test/testcases/chunked-empty.response test/testcases/chunked.response \ - test/testcases/chunked-trailers.response \ - test/testcases/deflate.response - -HEADERS = serf.h serf_bucket_types.h serf_bucket_util.h - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -pkgconfigdir=$(libdir)/pkgconfig - -LIBTOOL = @APR_LIBTOOL@ -LTFLAGS = @LTFLAGS@ --tag=CC -CC = @CC@ -CFLAGS = @EXTRA_CFLAGS@ @CFLAGS@ -CPPFLAGS = @EXTRA_CPPFLAGS@ @CPPFLAGS@ -INCLUDES = -I$(srcdir) @APR_INCLUDES@ @APU_INCLUDES@ @EXTRA_INCLUDES@ -MKDIR = @mkdir_p@ -INSTALL = @INSTALL@ - -LDFLAGS = @EXTRA_LDFLAGS@ @LDFLAGS@ -LIBS = @EXTRA_LIBS@ @SERF_LIBS@ -lz -lssl -lcrypto - -all: $(TARGET_LIB) $(PROGRAMS) - -context.lo: context.c $(HEADERS) -incoming.lo: incoming.c $(HEADERS) -outgoing.lo: outgoing.c $(HEADERS) -ssltunnel.lo: ssltunnel.c $(HEADERS) -buckets/aggregate_buckets.lo: buckets/aggregate_buckets.c $(HEADERS) -buckets/request_buckets.lo: buckets/request_buckets.c $(HEADERS) -buckets/buckets.lo: buckets/buckets.c $(HEADERS) -buckets/simple_buckets.lo: buckets/simple_buckets.c $(HEADERS) -buckets/file_buckets.lo: buckets/file_buckets.c $(HEADERS) -buckets/mmap_buckets.lo: buckets/mmap_buckets.c $(HEADERS) -buckets/socket_buckets.lo: buckets/socket_buckets.c $(HEADERS) -buckets/response_buckets.lo: buckets/response_buckets.c $(HEADERS) -buckets/headers_buckets.lo: buckets/headers_buckets.c $(HEADERS) -buckets/allocator.lo: buckets/allocator.c $(HEADERS) -buckets/dechunk_buckets.lo: buckets/dechunk_buckets.c $(HEADERS) -buckets/deflate_buckets.lo: buckets/deflate_buckets.c $(HEADERS) -buckets/limit_buckets.lo: buckets/limit_buckets.c $(HEADERS) -buckets/ssl_buckets.lo: buckets/ssl_buckets.c $(HEADERS) -buckets/barrier_buckets.lo: buckets/barrier_buckets.c $(HEADERS) -buckets/chunk_buckets.lo: buckets/chunk_buckets.c $(HEADERS) -buckets/bwtp_buckets.lo: buckets/bwtp_buckets.c $(HEADERS) -buckets/iovec_buckets.lo: buckets/iovec_buckets.c $(HEADERS) - -test/serf_get.lo: test/serf_get.c $(HEADERS) -test/serf_response.lo: test/serf_response.c $(HEADERS) -test/serf_request.lo: test/serf_request.c $(HEADERS) -test/serf_server.lo: test/serf_server.c $(HEADERS) -test/serf_spider.lo: test/serf_spider.c $(HEADERS) -test/serf_bwtp.lo: test/serf_bwtp.c $(HEADERS) - -test/CuTest.lo: test/CuTest.c $(HEADERS) -test/test_all.lo: test/test_all.c $(HEADERS) -test/test_util.lo: test/test_util.c $(HEADERS) -test/test_buckets.lo: test/test_buckets.c $(HEADERS) -test/test_context.lo: test/test_context.c $(HEADERS) -test/test_ssl.lo: test/test_ssl.c $(HEADERS) - -$(TARGET_LIB): $(OBJECTS) - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -rpath $(libdir) -o $@ $(OBJECTS) $(LIBS) - -test/serf_get: $(TARGET_LIB) test/serf_get.lo - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_get.lo $(LIBS) - -test/serf_response: $(TARGET_LIB) test/serf_response.lo - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_response.lo $(LIBS) - -test/serf_request: $(TARGET_LIB) test/serf_request.lo - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_request.lo $(LIBS) - -test/serf_server: $(TARGET_LIB) test/serf_server.lo - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_server.lo $(LIBS) - -test/serf_spider: $(TARGET_LIB) test/serf_spider.lo - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_spider.lo $(LIBS) - -test/serf_bwtp: $(TARGET_LIB) test/serf_bwtp.lo - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_bwtp.lo $(LIBS) - -test/test_all: $(TARGET_LIB) $(TEST_SUITE_OBJECTS) - $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) $(TEST_SUITE_OBJECTS) $(LIBS) - -check: test/serf_response test/test_all - @for i in $(TESTCASES); \ - do echo "== Testing $$i =="; \ - ./test/serf_response $(srcdir)/$$i; \ - done; - @echo "== Running test_all =="; - @./test/test_all - -install: $(TARGET_LIB) - $(MKDIR) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) $(DESTDIR)$(pkgconfigdir) - $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) -m 644 $(TARGET_LIB) $(DESTDIR)$(libdir) - for i in $(srcdir)/*.h; do \ - $(INSTALL) -m 644 $$i $(DESTDIR)$(includedir); \ - done - $(INSTALL) -m 644 serf.pc $(DESTDIR)$(pkgconfigdir)/serf-$(SERF_MAJOR_VERSION).pc - -clean: - rm -f $(TARGET_LIB) $(OBJECTS) $(OBJECTS:.lo=.o) $(PROGRAMS) $(TEST_OBJECTS) $(TEST_OBJECTS:.lo=.o) $(TEST_SUITE_OBJECTS) $(TEST_SUITE_OBJECTS:.lo=.o) - for subdir in . buckets test; do \ - (cd $$subdir && rm -rf .libs) ; \ - done - -distclean: clean - rm -f Makefile serf.pc config.log config.status - -.SUFFIXES: -.SUFFIXES: .c .lo .o - -mkdir-vpath: - @if [ ! -d auth ]; then \ - $(MKDIR) auth; \ - fi; - @if [ ! -d buckets ]; then \ - $(MKDIR) buckets; \ - fi; - @if [ ! -d test ]; then \ - $(MKDIR) test; \ - fi; - @if [ ! -d test/server ]; then \ - $(MKDIR) test/server; \ - fi; - @if [ ! -r test/serftestca.pem ]; then \ - cp -f $(srcdir)/test/serftestca.pem test/; \ - fi; - -.c.lo: - $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(INCLUDES) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< && touch $@ diff -Nru serf-1.1.0/README serf-1.3.3/README --- serf-1.1.0/README 2007-08-26 07:27:48.000000000 +0000 +++ serf-1.3.3/README 2013-08-15 09:13:20.000000000 +0000 @@ -14,25 +14,80 @@ ---- -Quick guide for the impatient +1. INSTALL - (Unix) - % ./configure - % make - % make install +1.1. SCons build system ----- +serf uses SCons 2.3 for its build system. If it is not installed on +your system, then you can install it onto your system. If you do not +have permissions, then you can download and install the "local" +version into your home directory. When installed privately, simply +create a symlink for 'scons' in your PATH to /path/to/scons/scons.py. + +Fetch the scons-local package: + http://prdownloads.sourceforge.net/scons/scons-local-2.3.0.tar.gz + + +1.2 Building serf + +To build serf: + +$ scons APR=/path/to/apr APU=/path/to/apu OPENSSL=/openssl/base PREFIX=/path/to/prefix + +The switches are recorded into .saved_config, so they only need to be +specified the first time scons is run. + +PREFIX should specify where serf should be installed. PREFIX defaults to +/usr/local. + +The default for the other three switches (APR, APU, OPENSSL) is /usr. + +The build system looks for apr-1-config at $APR/bin/apr-1-config, or +the path should indicate apr-1-config itself. Similarly for the path +to apu-1-config. + +OPENSSL should specify the root of the install (eg. /opt/local). The +includes will be found OPENSSL/include and libraries at OPENSSL/lib. + +If you wish to use VPATH-style builds (where objects are created in a +distinct directory from the source), you can use: + +$ scons -Y /path/to/serf/source + +If you plan to install the library on a system that uses different +paths for architecture dependent files, specify LIBDIR. LIBDIR defaults +to /usr/local/lib otherwise. Example for a 64 bit GNU/Linux system: + +$ scons PREFIX=/usr/ LIBDIR=/usr/lib64 + +At any point, the current settings can be examined: + +$ scons --help + + +1.3 Running the test suite + +$ scons check + + +1.4 Installing serf + +$ scons install + +Note that the PREFIX variable should have been specified in a previous +invocation of scons (and saved into .saved_config), or it can be +specified on the install command line: -Building serf from a Subversion checkout (non-packaged releases) +$ scons PREFIX=/some/path install -We suggest that you try out 'serfmake'. +Distribution package maintainers regulary install to a buildroot, and +would normally use something like below in their build systems, with +placeholders for the specific paths: - % ./serfmake --prefix=/usr/local/serf --with-apr=/usr/local/apr install +$ scons PREFIX=/usr/ LIBDIR=/usr/lib64 +$ scons install --install-sandbox=/path/to/buildroot -If you want to use the autoconf build system and are using a Subversion -checkout, you need to run buildconf and have APR and APR-util sources handy. - % ./buildconf --with-apr=/path/to/apr --with-apr-util=/path/to/apr-util - (By default, buildconf will look in . and ../ for apr and apr-util.) +1.4 Cleaning up the build -Then, you can use ./configure, make, etc. +$ scons -c diff -Nru serf-1.1.0/SConstruct serf-1.3.3/SConstruct --- serf-1.1.0/SConstruct 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/SConstruct 2013-10-04 15:11:04.000000000 +0000 @@ -0,0 +1,471 @@ +# -*- python -*- +# +# Copyright 2011-2012 Justin Erenkrantz and Greg Stein +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import sys +import os +import re + +EnsureSConsVersion(2,3,0) + +HEADER_FILES = ['serf.h', + 'serf_bucket_types.h', + 'serf_bucket_util.h', + ] + +# where we save the configuration variables +SAVED_CONFIG = '.saved_config' + +# Variable class that does no validation on the input +def _converter(val): + """ + """ + if val == 'none': + val = [] + else: + val = val.split(' ') + return val + +def RawListVariable(key, help, default): + """ + The input parameters describe a 'raw string list' option. This class + accepts a space-separated string and converts it to a list. + """ + return (key, '%s' % (help), default, None, lambda val: _converter(val)) + +# Custom path validator, creates directory when a specified option is set. +# To be used to ensure a PREFIX directory is only created when installing. +def createPathIsDirCreateWithTarget(target): + def my_validator(key, val, env): + build_targets = (map(str, BUILD_TARGETS)) + if target in build_targets: + return PathVariable.PathIsDirCreate(key, val, env) + else: + return PathVariable.PathAccept(key, val, env) + return my_validator + +# default directories +if sys.platform == 'win32': + default_incdir='..' + default_libdir='..' + default_prefix='Debug' +else: + default_incdir='/usr' + default_libdir='$PREFIX/lib' + default_prefix='/usr/local' + +opts = Variables(files=[SAVED_CONFIG]) +opts.AddVariables( + PathVariable('PREFIX', + 'Directory to install under', + default_prefix, + createPathIsDirCreateWithTarget('install')), + PathVariable('LIBDIR', + 'Directory to install architecture dependent libraries under', + default_libdir, + createPathIsDirCreateWithTarget('install')), + PathVariable('APR', + "Path to apr-1-config, or to APR's install area", + default_incdir, + PathVariable.PathAccept), + PathVariable('APU', + "Path to apu-1-config, or to APR's install area", + default_incdir, + PathVariable.PathAccept), + PathVariable('OPENSSL', + "Path to OpenSSL's install area", + default_incdir, + PathVariable.PathIsDir), + PathVariable('ZLIB', + "Path to zlib's install area", + default_incdir, + PathVariable.PathIsDir), + PathVariable('GSSAPI', + "Path to GSSAPI's install area", + None, + None), + BoolVariable('DEBUG', + "Enable debugging info and strict compile warnings", + False), + BoolVariable('APR_STATIC', + "Enable using a static compiled APR", + False), + RawListVariable('CC', "Command name or path of the C compiler", None), + RawListVariable('CFLAGS', "Extra flags for the C compiler (space-separated)", + None), + RawListVariable('LIBS', "Extra libraries passed to the linker, " + "e.g. \"-l -l\" (space separated)", None), + RawListVariable('LINKFLAGS', "Extra flags for the linker (space-separated)", + None), + RawListVariable('CPPFLAGS', "Extra flags for the C preprocessor " + "(space separated)", None), + ) + +if sys.platform == 'win32': + opts.AddVariables( + # By default SCons builds for the host platform on Windows, when using + # a supported compiler (E.g. VS2010/VS2012). Allow overriding + + # Note that Scons 1.3 only supports this on Windows and only when + # constructing Environment(). Later changes to TARGET_ARCH are ignored + EnumVariable('TARGET_ARCH', + "Platform to build for (x86|x64|win32|x86_64)", + 'x86', + allowed_values=('x86', 'x86_64', 'ia64'), + map={'X86' : 'x86', + 'win32': 'x86', + 'Win32': 'x86', + 'x64' : 'x86_64', + 'X64' : 'x86_64' + }), + + EnumVariable('MSVC_VERSION', + "Visual C++ to use for building (E.g. 11.0, 9.0)", + None, + allowed_values=('12.0', '11.0', '10.0', '9.0', '8.0', '6.0') + ), + + # We always documented that we handle an install layout, but in fact we + # hardcoded source layouts. Allow disabling this behavior. + # ### Fix default? + BoolVariable('SOURCE_LAYOUT', + "Assume a source layout instead of install layout", + True), + ) + +env = Environment(variables=opts, + tools=('default', 'textfile',), + CPPPATH=['.', ], + ) + +env.Append(BUILDERS = { + 'GenDef' : + Builder(action = sys.executable + ' build/gen_def.py $SOURCES > $TARGET', + suffix='.def', src_suffix='.h') + }) + +match = re.search('SERF_MAJOR_VERSION ([0-9]+).*' + 'SERF_MINOR_VERSION ([0-9]+).*' + 'SERF_PATCH_VERSION ([0-9]+)', + env.File('serf.h').get_contents(), + re.DOTALL) +MAJOR, MINOR, PATCH = [int(x) for x in match.groups()] +env.Append(MAJOR=str(MAJOR)) +env.Append(MINOR=str(MINOR)) +env.Append(PATCH=str(PATCH)) + +# Calling external programs is okay if we're not cleaning or printing help. +# (cleaning: no sense in fetching information; help: we may not know where +# they are) +CALLOUT_OKAY = not (env.GetOption('clean') or env.GetOption('help')) + + +# HANDLING OF OPTION VARIABLES + +unknown = opts.UnknownVariables() +if unknown: + print 'Unknown variables:', ', '.join(unknown.keys()) + Exit(1) + +apr = str(env['APR']) +apu = str(env['APU']) +zlib = str(env['ZLIB']) +gssapi = env.get('GSSAPI', None) + +if gssapi and os.path.isdir(gssapi): + krb5_config = os.path.join(gssapi, 'bin', 'krb5-config') + if os.path.isfile(krb5_config): + gssapi = krb5_config + env['GSSAPI'] = krb5_config + +debug = env.get('DEBUG', None) +aprstatic = env.get('APR_STATIC', None) + +Help(opts.GenerateHelpText(env)) +opts.Save(SAVED_CONFIG, env) + + +# PLATFORM-SPECIFIC BUILD TWEAKS + +thisdir = os.getcwd() +libdir = '$LIBDIR' +incdir = '$PREFIX/include/serf-$MAJOR' + +# This version string is used in the dynamic library name, and for Mac OS X also +# for the current_version and compatibility_version options in the .dylib +# +# Unfortunately we can't set the .dylib compatibility_version option separately +# from current_version, so don't use the PATCH level to avoid that build and +# runtime patch levels have to be identical. +env['SHLIBVERSION'] = '%d.%d.%d' % (MAJOR, MINOR, 0) + +LIBNAME = 'libserf-%d' % (MAJOR,) +if sys.platform != 'win32': + LIBNAMESTATIC = LIBNAME +else: + LIBNAMESTATIC = 'serf-${MAJOR}' + +env.Append(RPATH=libdir, + PDB='${TARGET.filebase}.pdb') + +if sys.platform == 'darwin': +# linkflags.append('-Wl,-install_name,@executable_path/%s.dylib' % (LIBNAME,)) + env.Append(LINKFLAGS='-Wl,-install_name,%s/%s.dylib' % (thisdir, LIBNAME,)) + +if sys.platform != 'win32': + ### gcc only. figure out appropriate test / better way to check these + ### flags, and check for gcc. + env.Append(CFLAGS='-std=c89') + + ### These warnings are not available on Solaris + if sys.platform != 'sunos5': + env.Append(CCFLAGS=['-Wdeclaration-after-statement', + '-Wmissing-prototypes', + '-Wall']) + + if debug: + env.Append(CCFLAGS='-g') + env.Append(CPPDEFINES=['DEBUG', '_DEBUG']) + else: + env.Append(CCFLAGS='-O2') + env.Append(CPPDEFINES='NDEBUG') + + ### works for Mac OS. probably needs to change + env.Append(LIBS=['ssl', 'crypto', 'z', ]) + + if sys.platform == 'sunos5': + env.Append(LIBS='m') +else: + # Warning level 4, no unused argument warnings + env.Append(CCFLAGS=['/W4', '/wd4100']) + + # Choose runtime and optimization + if debug: + # Disable optimizations for debugging, use debug DLL runtime + env.Append(CCFLAGS=['/Od', '/MDd']) + env.Append(CPPDEFINES=['DEBUG', '_DEBUG']) + else: + # Optimize for speed, use DLL runtime + env.Append(CCFLAGS=['/O2', '/MD']) + env.Append(CPPDEFINES='NDEBUG') + env.Append(LINKFLAGS='/RELEASE') + +# PLAN THE BUILD +SHARED_SOURCES = [] +if sys.platform == 'win32': + env.GenDef(['serf.h','serf_bucket_types.h', 'serf_bucket_util.h']) + SHARED_SOURCES.append(['serf.def']) + +SOURCES = Glob('*.c') + Glob('buckets/*.c') + Glob('auth/*.c') + +lib_static = env.StaticLibrary(LIBNAMESTATIC, SOURCES) +lib_shared = env.SharedLibrary(LIBNAME, SOURCES + SHARED_SOURCES) + +if aprstatic: + env.Append(CPPDEFINES=['APR_DECLARE_STATIC', 'APU_DECLARE_STATIC']) + +if sys.platform == 'win32': + env.Append(LIBS=['user32.lib', 'advapi32.lib', 'gdi32.lib', 'ws2_32.lib', + 'crypt32.lib', 'mswsock.lib', 'rpcrt4.lib', 'secur32.lib']) + + # Get apr/apu information into our build + env.Append(CPPDEFINES=['WIN32','WIN32_LEAN_AND_MEAN','NOUSER', + 'NOGDI', 'NONLS','NOCRYPT']) + + if env.get('TARGET_ARCH', None) == 'x86_64': + env.Append(CPPDEFINES=['WIN64']) + + if aprstatic: + apr_libs='apr-1.lib' + apu_libs='aprutil-1.lib' + else: + apr_libs='libapr-1.lib' + apu_libs='libaprutil-1.lib' + + env.Append(LIBS=[apr_libs, apu_libs]) + if not env.get('SOURCE_LAYOUT', None): + env.Append(LIBPATH=['$APR/lib', '$APU/lib'], + CPPPATH=['$APR/include/apr-1', '$APU/include/apr-1']) + elif aprstatic: + env.Append(LIBPATH=['$APR/LibR','$APU/LibR'], + CPPPATH=['$APR/include', '$APU/include']) + else: + env.Append(LIBPATH=['$APR/Release','$APU/Release'], + CPPPATH=['$APR/include', '$APU/include']) + + # zlib + env.Append(LIBS='zlib.lib') + if not env.get('SOURCE_LAYOUT', None): + env.Append(CPPPATH='$ZLIB/include', + LIBPATH='$ZLIB/lib') + else: + env.Append(CPPPATH='$ZLIB', + LIBPATH='$ZLIB') + + # openssl + env.Append(LIBS=['libeay32.lib', 'ssleay32.lib']) + if not env.get('SOURCE_LAYOUT', None): + env.Append(CPPPATH='$OPENSSL/include/openssl', + LIBPATH='$OPENSSL/lib') + elif 0: # opensslstatic: + env.Append(CPPPATH='$OPENSSL/inc32', + LIBPATH='$OPENSSL/out32') + else: + env.Append(CPPPATH='$OPENSSL/inc32', + LIBPATH='$OPENSSL/out32dll') +else: + if os.path.isdir(apr): + apr = os.path.join(apr, 'bin', 'apr-1-config') + env['APR'] = apr + if os.path.isdir(apu): + apu = os.path.join(apu, 'bin', 'apu-1-config') + env['APU'] = apu + + ### we should use --cc, but that is giving some scons error about an implict + ### dependency upon gcc. probably ParseConfig doesn't know what to do with + ### the apr-1-config output + if CALLOUT_OKAY: + env.ParseConfig('$APR --cflags --cppflags --ldflags --includes' + ' --link-ld --libs') + env.ParseConfig('$APU --ldflags --includes --link-ld --libs') + + ### there is probably a better way to run/capture output. + ### env.ParseConfig() may be handy for getting this stuff into the build + if CALLOUT_OKAY: + apr_libs = os.popen(env.subst('$APR --link-libtool --libs')).read().strip() + apu_libs = os.popen(env.subst('$APU --link-libtool --libs')).read().strip() + else: + apr_libs = '' + apu_libs = '' + + env.Append(CPPPATH='$OPENSSL/include') + env.Append(LIBPATH='$OPENSSL/lib') + + +# If build with gssapi, get its information and define SERF_HAVE_GSSAPI +if gssapi and CALLOUT_OKAY: + env.ParseConfig('$GSSAPI --cflags gssapi') + def parse_libs(env, cmd, unique=1): + env['GSSAPI_LIBS'] = cmd.strip() + return env.MergeFlags(cmd, unique) + env.ParseConfig('$GSSAPI --libs gssapi', parse_libs) + env.Append(CPPDEFINES='SERF_HAVE_GSSAPI') +if sys.platform == 'win32': + env.Append(CPPDEFINES=['SERF_HAVE_SSPI']) + +# On some systems, the -R values that APR describes never make it into actual +# RPATH flags. We'll manually map all directories in LIBPATH into new +# flags to set RPATH values. +for d in env['LIBPATH']: + env.Append(RPATH=':'+d) + +# Set up the construction of serf-*.pc +pkgconfig = env.Textfile('serf-%d.pc' % (MAJOR,), + env.File('build/serf.pc.in'), + SUBST_DICT = { + '@MAJOR@': str(MAJOR), + '@PREFIX@': '$PREFIX', + '@LIBDIR@': '$LIBDIR', + '@INCLUDE_SUBDIR@': 'serf-%d' % (MAJOR,), + '@VERSION@': '%d.%d.%d' % (MAJOR, MINOR, PATCH), + '@LIBS@': '%s %s %s -lz' % (apu_libs, apr_libs, + env.get('GSSAPI_LIBS')), + }) + +env.Default(lib_static, lib_shared, pkgconfig) + +if CALLOUT_OKAY: + conf = Configure(env) + + ### some configuration stuffs + + env = conf.Finish() + + +# INSTALLATION STUFF + +install_static = env.Install(libdir, lib_static) +install_shared = env.InstallVersionedLib(libdir, lib_shared) + +if sys.platform == 'darwin': + # Change the shared library install name (id) to its final name and location. + # Notes: + # If --install-sandbox= is specified, install_shared_path will point + # to a path in the sandbox. We can't use that path because the sandbox is + # only a temporary location. The id should be the final target path. + # Also, we shouldn't use the complete version number for id, as that'll + # make applications depend on the exact major.minor.patch version of serf. + + install_shared_path = install_shared[0].abspath + target_install_shared_path = os.path.join(libdir, '%s.dylib' % LIBNAME) + env.AddPostAction(install_shared, ('install_name_tool -id %s %s' + % (target_install_shared_path, + install_shared_path))) + +env.Alias('install-lib', [install_static, install_shared, + ]) +env.Alias('install-inc', env.Install(incdir, HEADER_FILES)) +env.Alias('install-pc', env.Install(os.path.join(libdir, 'pkgconfig'), + pkgconfig)) +env.Alias('install', ['install-lib', 'install-inc', 'install-pc', ]) + + +# TESTS +### make move to a separate scons file in the test/ subdir? + +tenv = env.Clone() + +TEST_PROGRAMS = [ 'serf_get', 'serf_response', 'serf_request', 'serf_spider', + 'test_all', 'serf_bwtp' ] +if sys.platform == 'win32': + TEST_EXES = [ os.path.join('test', '%s.exe' % (prog)) for prog in TEST_PROGRAMS ] +else: + TEST_EXES = [ os.path.join('test', '%s' % (prog)) for prog in TEST_PROGRAMS ] + +env.AlwaysBuild(env.Alias('check', TEST_EXES, sys.executable + ' build/check.py', + ENV={'PATH' : os.environ['PATH']})) + +# Find the (dynamic) library in this directory +tenv.Replace(RPATH=thisdir) +tenv.Prepend(LIBS=[LIBNAMESTATIC, ], + LIBPATH=[thisdir, ]) + +testall_files = [ + 'test/test_all.c', + 'test/CuTest.c', + 'test/test_util.c', + 'test/test_context.c', + 'test/test_buckets.c', + 'test/test_auth.c', + 'test/mock_buckets.c', + 'test/test_ssl.c', + 'test/server/test_server.c', + 'test/server/test_sslserver.c', + ] + +for proggie in TEST_EXES: + if 'test_all' in proggie: + tenv.Program(proggie, testall_files ) + else: + tenv.Program(target = proggie, source = [proggie.replace('.exe','') + '.c']) + + +# HANDLE CLEANING + +if env.GetOption('clean'): + # When we're cleaning, we want the dependency tree to include "everything" + # that could be built. Thus, include all of the tests. + env.Default('check') diff -Nru serf-1.1.0/auth/auth.c serf-1.3.3/auth/auth.c --- serf-1.1.0/auth/auth.c 2011-06-25 09:46:22.000000000 +0000 +++ serf-1.3.3/auth/auth.c 2013-09-29 06:37:46.000000000 +0000 @@ -20,9 +20,12 @@ #include #include #include +#include static apr_status_t -default_auth_response_handler(int code, +default_auth_response_handler(const serf__authn_scheme_t *scheme, + peer_t peer, + int code, serf_connection_t *conn, serf_request_t *request, serf_bucket_t *response, @@ -31,40 +34,42 @@ return APR_SUCCESS; } +/* These authentication schemes are in order of decreasing security, the topmost + scheme will be used first when the server supports it. + + Each set of handlers should support both server (401) and proxy (407) + authentication. + + Use lower case for the scheme names to enable case insensitive matching. + */ static const serf__authn_scheme_t serf_authn_schemes[] = { +#ifdef SERF_HAVE_SPNEGO { - 401, - "Basic", - SERF_AUTHN_BASIC, - serf__init_basic, - serf__init_basic_connection, - serf__handle_basic_auth, - serf__setup_request_basic_auth, - default_auth_response_handler, - }, - { - 407, - "Basic", - SERF_AUTHN_BASIC, - serf__init_basic, - serf__init_basic_connection, - serf__handle_basic_auth, - serf__setup_request_basic_auth, - default_auth_response_handler, + "Negotiate", + "negotiate", + SERF_AUTHN_NEGOTIATE, + serf__init_spnego, + serf__init_spnego_connection, + serf__handle_spnego_auth, + serf__setup_request_spnego_auth, + serf__validate_response_spnego_auth, }, +#ifdef WIN32 { - 401, - "Digest", - SERF_AUTHN_DIGEST, - serf__init_digest, - serf__init_digest_connection, - serf__handle_digest_auth, - serf__setup_request_digest_auth, - serf__validate_response_digest_auth, + "NTLM", + "ntlm", + SERF_AUTHN_NTLM, + serf__init_spnego, + serf__init_spnego_connection, + serf__handle_spnego_auth, + serf__setup_request_spnego_auth, + serf__validate_response_spnego_auth, }, +#endif /* #ifdef WIN32 */ +#endif /* SERF_HAVE_SPNEGO */ { - 407, "Digest", + "digest", SERF_AUTHN_DIGEST, serf__init_digest, serf__init_digest_connection, @@ -72,18 +77,16 @@ serf__setup_request_digest_auth, serf__validate_response_digest_auth, }, -#ifdef SERF_HAVE_KERB { - 401, - "Negotiate", - SERF_AUTHN_NEGOTIATE, - serf__init_kerb, - serf__init_kerb_connection, - serf__handle_kerb_auth, - serf__setup_request_kerb_auth, - serf__validate_response_kerb_auth, + "Basic", + "basic", + SERF_AUTHN_BASIC, + serf__init_basic, + serf__init_basic_connection, + serf__handle_basic_auth, + serf__setup_request_basic_auth, + default_auth_response_handler, }, -#endif /* ADD NEW AUTHENTICATION IMPLEMENTATIONS HERE (as they're written) */ /* sentinel */ @@ -91,21 +94,6 @@ }; -/** - * Baton passed to the response header callback function - */ -typedef struct { - int code; - apr_status_t status; - const char *header; - serf_request_t *request; - serf_bucket_t *response; - void *baton; - apr_pool_t *pool; - const serf__authn_scheme_t *scheme; - const char *last_scheme_name; -} auth_baton_t; - /* Reads and discards all bytes in the response body. */ static apr_status_t discard_body(serf_bucket_t *response) { @@ -131,93 +119,140 @@ * * Returns a non-0 value of a matching handler was found. */ -static int handle_auth_header(void *baton, - const char *key, - const char *header) +static int handle_auth_headers(int code, + void *baton, + apr_hash_t *hdrs, + serf_request_t *request, + serf_bucket_t *response, + apr_pool_t *pool) { - auth_baton_t *ab = baton; - int scheme_found = FALSE; - const char *auth_name; - const char *auth_attr; - const serf__authn_scheme_t *scheme = NULL; - serf_connection_t *conn = ab->request->conn; + const serf__authn_scheme_t *scheme; + serf_connection_t *conn = request->conn; serf_context_t *ctx = conn->ctx; + apr_status_t status; - /* We're only interested in xxxx-Authenticate headers. */ - if (strcmp(key, ab->header) != 0) - return 0; - - /* Extract the authentication scheme name, and prepare for reading - the attributes. */ - auth_attr = strchr(header, ' '); - if (auth_attr) { - auth_name = apr_pstrmemdup(ab->pool, header, auth_attr - header); - ++auth_attr; - } - else - auth_name = header; - - ab->last_scheme_name = auth_name; + status = SERF_ERROR_AUTHN_NOT_SUPPORTED; /* Find the matching authentication handler. Note that we don't reuse the auth scheme stored in the context, as that may have changed. (ex. fallback from ntlm to basic.) */ - for (scheme = serf_authn_schemes; scheme->code != 0; ++scheme) { - if (ab->code == scheme->code && - strcmp(auth_name, scheme->name) == 0 && - ctx->authn_types & scheme->type) { - serf__auth_handler_func_t handler = scheme->handle_func; - apr_status_t status = 0; - - /* If this is the first time we use this scheme on this connection, - make sure to initialize the authentication handler first. */ - if (ab->code == 401 && ctx->authn_info.scheme != scheme) { - status = scheme->init_ctx_func(ab->code, ctx, ctx->pool); - if (!status) { - status = scheme->init_conn_func(ab->code, conn, conn->pool); - - if (!status) - ctx->authn_info.scheme = scheme; - else - ctx->authn_info.scheme = NULL; - } - } - else if (ab->code == 407 && ctx->proxy_authn_info.scheme != scheme) { - status = scheme->init_ctx_func(ab->code, ctx, ctx->pool); - if (!status) { - status = scheme->init_conn_func(ab->code, conn, conn->pool); - - if (!status) - ctx->proxy_authn_info.scheme = scheme; - else - ctx->proxy_authn_info.scheme = NULL; - } - } + for (scheme = serf_authn_schemes; scheme->name != 0; ++scheme) { + const char *auth_hdr; + serf__auth_handler_func_t handler; + serf__authn_info_t *authn_info; + + if (! (ctx->authn_types & scheme->type)) + continue; + + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "Client supports: %s\n", scheme->name); + + auth_hdr = apr_hash_get(hdrs, scheme->key, APR_HASH_KEY_STRING); + + if (!auth_hdr) + continue; + + if (code == 401) { + authn_info = serf__get_authn_info_for_server(conn); + } else { + authn_info = &ctx->proxy_authn_info; + } + + if (authn_info->failed_authn_types & scheme->type) { + /* Skip this authn type since we already tried it before. */ + continue; + } + + /* Found a matching scheme */ + status = APR_SUCCESS; + + handler = scheme->handle_func; + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "... matched: %s\n", scheme->name); + + /* If this is the first time we use this scheme on this context and/or + this connection, make sure to initialize the authentication handler + first. */ + if (authn_info->scheme != scheme) { + status = scheme->init_ctx_func(code, ctx, ctx->pool); if (!status) { - scheme_found = TRUE; - ab->scheme = scheme; - status = handler(ab->code, ab->request, ab->response, - header, auth_attr, ab->baton, ctx->pool); + status = scheme->init_conn_func(scheme, code, conn, + conn->pool); + if (!status) + authn_info->scheme = scheme; + else + authn_info->scheme = NULL; } + } - /* If the authentication fails, cache the error for now. Try the - next available scheme. If there's none raise the error. */ - if (status) { - scheme_found = FALSE; - scheme = NULL; + if (!status) { + const char *auth_attr = strchr(auth_hdr, ' '); + if (auth_attr) { + auth_attr++; } - /* Let the caller now if the authentication setup was succesful - or not. */ - ab->status = status; - break; + status = handler(code, request, response, + auth_hdr, auth_attr, baton, ctx->pool); } + + if (status == APR_SUCCESS) + break; + + /* No success authenticating with this scheme, try the next. + If no more authn schemes are found the status of this scheme will be + returned. + */ + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "%s authentication failed.\n", scheme->name); + + /* Clear per-request auth_baton when switching to next auth scheme. */ + request->auth_baton = NULL; + + /* Remember failed auth types to skip in future. */ + authn_info->failed_authn_types |= scheme->type; } - /* If a matching scheme handler was found, we can stop iterating - over the response headers - so return a non-0 value. */ - return scheme_found; + return status; +} + +/** + * Baton passed to the store_header_in_dict callback function + */ +typedef struct { + const char *header; + apr_pool_t *pool; + apr_hash_t *hdrs; +} auth_baton_t; + +static int store_header_in_dict(void *baton, + const char *key, + const char *header) +{ + auth_baton_t *ab = baton; + const char *auth_attr; + char *auth_name, *c; + + /* We're only interested in xxxx-Authenticate headers. */ + if (strcasecmp(key, ab->header) != 0) + return 0; + + /* Extract the authentication scheme name. */ + auth_attr = strchr(header, ' '); + if (auth_attr) { + auth_name = apr_pstrmemdup(ab->pool, header, auth_attr - header); + } + else + auth_name = apr_pstrmemdup(ab->pool, header, strlen(header)); + + /* Convert scheme name to lower case to enable case insensitive matching. */ + for (c = auth_name; *c != '\0'; c++) + *c = (char)apr_tolower(*c); + + apr_hash_set(ab->hdrs, auth_name, APR_HASH_KEY_STRING, + apr_pstrdup(ab->pool, header)); + + return 0; } /* Dispatch authentication handling. This function matches the possible @@ -235,11 +270,7 @@ auth_baton_t ab = { 0 }; const char *auth_hdr; - ab.code = code; - ab.status = APR_SUCCESS; - ab.request = request; - ab.response = response; - ab.baton = baton; + ab.hdrs = apr_hash_make(pool); ab.pool = pool; /* Before iterating over all authn headers, check if there are any. */ @@ -254,9 +285,12 @@ if (!auth_hdr) { return SERF_ERROR_AUTHN_FAILED; } + serf__log_skt(AUTH_VERBOSE, __FILE__, request->conn->skt, + "%s authz required. Response header(s): %s\n", + code == 401 ? "Server" : "Proxy", auth_hdr); - /* Iterate over all headers. Try to find a matching authentication scheme - handler. + + /* Store all WWW- or Proxy-Authenticate headers in a dictionary. Note: it is possible to have multiple Authentication: headers. We do not want to combine them (per normal header combination rules) as that @@ -265,18 +299,13 @@ work with. */ serf_bucket_headers_do(hdrs, - handle_auth_header, + store_header_in_dict, &ab); - if (ab.status != APR_SUCCESS) - return ab.status; - - if (!ab.scheme || ab.scheme->name == NULL) { - /* No matching authentication found. */ - return SERF_ERROR_AUTHN_NOT_SUPPORTED; - } - } else { - /* Validate the response authn headers if needed. */ + /* Iterate over all authentication schemes, in order of decreasing + security. Try to find a authentication schema the server support. */ + return handle_auth_headers(code, baton, ab.hdrs, + request, response, pool); } return APR_SUCCESS; @@ -295,6 +324,8 @@ *consumed_response = 0; + /* TODO: the response bucket was created by the application, not at all + guaranteed that this is of type response_bucket!! */ status = serf_bucket_response_status(response, &sl); if (SERF_BUCKET_READ_ERROR(status)) { return status; @@ -337,11 +368,52 @@ /* Requeue the request with the necessary auth headers. */ /* ### Application doesn't know about this request! */ - serf_connection_priority_request_create(request->conn, - request->setup, - request->setup_baton); + if (request->ssltunnel) { + serf__ssltunnel_request_create(request->conn, + request->setup, + request->setup_baton); + } else { + serf_connection_priority_request_create(request->conn, + request->setup, + request->setup_baton); + } return APR_EOF; + } else { + serf__validate_response_func_t validate_resp; + serf_connection_t *conn = request->conn; + serf_context_t *ctx = conn->ctx; + serf__authn_info_t *authn_info; + apr_status_t resp_status = APR_SUCCESS; + + + /* Validate the response server authn headers. */ + authn_info = serf__get_authn_info_for_server(conn); + if (authn_info->scheme) { + validate_resp = authn_info->scheme->validate_response_func; + resp_status = validate_resp(authn_info->scheme, HOST, sl.code, + conn, request, response, pool); + } + + /* Validate the response proxy authn headers. */ + authn_info = &ctx->proxy_authn_info; + if (!resp_status && authn_info->scheme) { + validate_resp = authn_info->scheme->validate_response_func; + resp_status = validate_resp(authn_info->scheme, PROXY, sl.code, + conn, request, response, pool); + } + + if (resp_status) { + /* If there was an error in the final step of the authentication, + consider the reponse body as invalid and discard it. */ + status = discard_body(response); + *consumed_response = 1; + if (!APR_STATUS_IS_EOF(status)) { + return status; + } + /* The whole body was discarded, now return our error. */ + return resp_status; + } } return APR_SUCCESS; @@ -372,3 +444,42 @@ apr_base64_encode(ptr, data, data_len); } + +const char *serf__construct_realm(peer_t peer, + serf_connection_t *conn, + const char *realm_name, + apr_pool_t *pool) +{ + if (peer == HOST) { + return apr_psprintf(pool, "<%s://%s:%d> %s", + conn->host_info.scheme, + conn->host_info.hostname, + conn->host_info.port, + realm_name); + } else { + serf_context_t *ctx = conn->ctx; + + return apr_psprintf(pool, " %s", + ctx->proxy_address->hostname, + ctx->proxy_address->port, + realm_name); + } +} + +serf__authn_info_t *serf__get_authn_info_for_server(serf_connection_t *conn) +{ + serf_context_t *ctx = conn->ctx; + serf__authn_info_t *authn_info; + + authn_info = apr_hash_get(ctx->server_authn_info, conn->host_url, + APR_HASH_KEY_STRING); + + if (!authn_info) { + authn_info = apr_pcalloc(ctx->pool, sizeof(serf__authn_info_t)); + apr_hash_set(ctx->server_authn_info, + apr_pstrdup(ctx->pool, conn->host_url), + APR_HASH_KEY_STRING, authn_info); + } + + return authn_info; +} diff -Nru serf-1.1.0/auth/auth.h serf-1.3.3/auth/auth.h --- serf-1.1.0/auth/auth.h 2010-02-22 17:36:00.000000000 +0000 +++ serf-1.3.3/auth/auth.h 2013-08-15 09:00:57.000000000 +0000 @@ -16,7 +16,7 @@ #ifndef AUTH_H #define AUTH_H -#include "auth_kerb.h" +#include "auth_spnego.h" #ifdef __cplusplus extern "C" { @@ -26,11 +26,19 @@ const char *data, apr_size_t data_len, apr_pool_t *pool); +/* Prefixes the realm_name with a string containing scheme, hostname and port + of the connection, for providing it to the application. */ +const char *serf__construct_realm(peer_t peer, + serf_connection_t *conn, + const char *realm_name, + apr_pool_t *pool); + /** Basic authentication **/ apr_status_t serf__init_basic(int code, serf_context_t *ctx, apr_pool_t *pool); -apr_status_t serf__init_basic_connection(int code, +apr_status_t serf__init_basic_connection(const serf__authn_scheme_t *scheme, + int code, serf_connection_t *conn, apr_pool_t *pool); apr_status_t serf__handle_basic_auth(int code, @@ -40,8 +48,10 @@ const char *auth_attr, void *baton, apr_pool_t *pool); -apr_status_t serf__setup_request_basic_auth(int code, +apr_status_t serf__setup_request_basic_auth(peer_t peer, + int code, serf_connection_t *conn, + serf_request_t *request, const char *method, const char *uri, serf_bucket_t *hdrs_bkt); @@ -50,7 +60,8 @@ apr_status_t serf__init_digest(int code, serf_context_t *ctx, apr_pool_t *pool); -apr_status_t serf__init_digest_connection(int code, +apr_status_t serf__init_digest_connection(const serf__authn_scheme_t *scheme, + int code, serf_connection_t *conn, apr_pool_t *pool); apr_status_t serf__handle_digest_auth(int code, @@ -60,42 +71,51 @@ const char *auth_attr, void *baton, apr_pool_t *pool); -apr_status_t serf__setup_request_digest_auth(int code, +apr_status_t serf__setup_request_digest_auth(peer_t peer, + int code, serf_connection_t *conn, + serf_request_t *request, const char *method, const char *uri, serf_bucket_t *hdrs_bkt); -apr_status_t serf__validate_response_digest_auth(int code, +apr_status_t serf__validate_response_digest_auth(const serf__authn_scheme_t *scheme, + peer_t peer, + int code, serf_connection_t *conn, serf_request_t *request, serf_bucket_t *response, apr_pool_t *pool); -#ifdef SERF_HAVE_KERB +#ifdef SERF_HAVE_SPNEGO /** Kerberos authentication **/ -apr_status_t serf__init_kerb(int code, - serf_context_t *ctx, - apr_pool_t *pool); -apr_status_t serf__init_kerb_connection(int code, - serf_connection_t *conn, - apr_pool_t *pool); -apr_status_t serf__handle_kerb_auth(int code, - serf_request_t *request, - serf_bucket_t *response, - const char *auth_hdr, - const char *auth_attr, - void *baton, - apr_pool_t *pool); -apr_status_t serf__setup_request_kerb_auth(int code, - serf_connection_t *conn, - const char *method, - const char *uri, - serf_bucket_t *hdrs_bkt); -apr_status_t serf__validate_response_kerb_auth(int code, - serf_connection_t *conn, - serf_request_t *request, - serf_bucket_t *response, - apr_pool_t *pool); +apr_status_t serf__init_spnego(int code, + serf_context_t *ctx, + apr_pool_t *pool); +apr_status_t serf__init_spnego_connection(const serf__authn_scheme_t *scheme, + int code, + serf_connection_t *conn, + apr_pool_t *pool); +apr_status_t serf__handle_spnego_auth(int code, + serf_request_t *request, + serf_bucket_t *response, + const char *auth_hdr, + const char *auth_attr, + void *baton, + apr_pool_t *pool); +apr_status_t serf__setup_request_spnego_auth(peer_t peer, + int code, + serf_connection_t *conn, + serf_request_t *request, + const char *method, + const char *uri, + serf_bucket_t *hdrs_bkt); +apr_status_t serf__validate_response_spnego_auth(const serf__authn_scheme_t *scheme, + peer_t peer, + int code, + serf_connection_t *conn, + serf_request_t *request, + serf_bucket_t *response, + apr_pool_t *pool); #endif /* SERF_HAVE_SPNEGO */ #ifdef __cplusplus diff -Nru serf-1.1.0/auth/auth_basic.c serf-1.3.3/auth/auth_basic.c --- serf-1.1.0/auth/auth_basic.c 2010-02-19 10:37:38.000000000 +0000 +++ serf-1.3.3/auth/auth_basic.c 2013-08-17 21:58:47.000000000 +0000 @@ -23,6 +23,8 @@ #include #include +/* Stores the context information related to Basic authentication. + This information is stored in the per server cache in the serf context. */ typedef struct basic_authn_info_t { const char *header; const char *value; @@ -41,12 +43,12 @@ apr_size_t tmp_len; serf_connection_t *conn = request->conn; serf_context_t *ctx = conn->ctx; - serf__authn_info_t *authn_info = (code == 401) ? &ctx->authn_info : - &ctx->proxy_authn_info; - basic_authn_info_t *basic_info = authn_info->baton; + serf__authn_info_t *authn_info; + basic_authn_info_t *basic_info; apr_status_t status; apr_pool_t *cred_pool; - char *username, *password; + char *username, *password, *realm_name; + const char *eq, *realm = NULL; /* Can't do Basic authentication if there's no callback to get username & password. */ @@ -54,20 +56,25 @@ return SERF_ERROR_AUTHN_FAILED; } - if (!authn_info->realm) { - char *realm_name = NULL; - const char *eq = strchr(auth_attr, '='); - - if (eq && strncasecmp(auth_attr, "realm", 5) == 0) { - realm_name = apr_pstrdup(pool, eq + 1); - if (realm_name[0] == '\"') { - apr_size_t realm_len; - - realm_len = strlen(realm_name); - if (realm_name[realm_len - 1] == '\"') { - realm_name[realm_len - 1] = '\0'; - realm_name++; - } + if (code == 401) { + authn_info = serf__get_authn_info_for_server(conn); + } else { + authn_info = &ctx->proxy_authn_info; + } + basic_info = authn_info->baton; + + realm_name = NULL; + eq = strchr(auth_attr, '='); + + if (eq && strncasecmp(auth_attr, "realm", 5) == 0) { + realm_name = apr_pstrdup(pool, eq + 1); + if (realm_name[0] == '\"') { + apr_size_t realm_len; + + realm_len = strlen(realm_name); + if (realm_name[realm_len - 1] == '\"') { + realm_name[realm_len - 1] = '\0'; + realm_name++; } } @@ -75,18 +82,18 @@ return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE; } - authn_info->realm = apr_psprintf(conn->pool, "<%s://%s:%d> %s", - conn->host_info.scheme, - conn->host_info.hostname, - conn->host_info.port, - realm_name); + realm = serf__construct_realm(code == 401 ? HOST : PROXY, + conn, realm_name, + pool); } /* Ask the application for credentials */ apr_pool_create(&cred_pool, pool); - status = (*ctx->cred_cb)(&username, &password, request, baton, - code, authn_info->scheme->name, - authn_info->realm, cred_pool); + status = serf__provide_credentials(ctx, + &username, &password, + request, baton, + code, authn_info->scheme->name, + realm, cred_pool); if (status) { apr_pool_destroy(cred_pool); return status; @@ -104,50 +111,65 @@ return APR_SUCCESS; } -/* For Basic authentication we expect all authn info to be the same for all - connections in the context (same realm, username, password). Therefore we - can keep the header value in the context instead of per connection. */ apr_status_t serf__init_basic(int code, serf_context_t *ctx, apr_pool_t *pool) { - if (code == 401) { - ctx->authn_info.baton = apr_pcalloc(pool, sizeof(basic_authn_info_t)); - } else { - ctx->proxy_authn_info.baton = apr_pcalloc(pool, sizeof(basic_authn_info_t)); - } - return APR_SUCCESS; } +/* For Basic authentication we expect all authn info to be the same for all + connections in the context to the same server (same realm, username, + password). Therefore we can keep the header value in the per-server store + context instead of per connection. + TODO: we currently don't cache this info per realm, so each time a request + 'switches realms', we have to ask the application for new credentials. */ apr_status_t -serf__init_basic_connection(int code, +serf__init_basic_connection(const serf__authn_scheme_t *scheme, + int code, serf_connection_t *conn, apr_pool_t *pool) { + serf_context_t *ctx = conn->ctx; + serf__authn_info_t *authn_info; + + if (code == 401) { + authn_info = serf__get_authn_info_for_server(conn); + } else { + authn_info = &ctx->proxy_authn_info; + } + + if (!authn_info->baton) { + authn_info->baton = apr_pcalloc(pool, sizeof(basic_authn_info_t)); + } + return APR_SUCCESS; } apr_status_t -serf__setup_request_basic_auth(int code, +serf__setup_request_basic_auth(peer_t peer, + int code, serf_connection_t *conn, + serf_request_t *request, const char *method, const char *uri, serf_bucket_t *hdrs_bkt) { serf_context_t *ctx = conn->ctx; - basic_authn_info_t *authn_info; + serf__authn_info_t *authn_info; + basic_authn_info_t *basic_info; - if (code == 401) { - authn_info = ctx->authn_info.baton; + if (peer == HOST) { + authn_info = serf__get_authn_info_for_server(conn); } else { - authn_info = ctx->proxy_authn_info.baton; + authn_info = &ctx->proxy_authn_info; } + basic_info = authn_info->baton; - if (authn_info && authn_info->header && authn_info->value) { - serf_bucket_headers_setn(hdrs_bkt, authn_info->header, - authn_info->value); + if (basic_info && basic_info->header && basic_info->value) { + serf_bucket_headers_setn(hdrs_bkt, basic_info->header, + basic_info->value); return APR_SUCCESS; } diff -Nru serf-1.1.0/auth/auth_digest.c serf-1.3.3/auth/auth_digest.c --- serf-1.1.0/auth/auth_digest.c 2010-02-19 10:37:38.000000000 +0000 +++ serf-1.3.3/auth/auth_digest.c 2013-10-03 18:17:40.000000000 +0000 @@ -27,8 +27,12 @@ /** Digest authentication, implements RFC 2617. **/ +/* TODO: add support for the domain attribute. This defines the protection + space, so that serf can decide per URI if it should reuse the cached + credentials for the server, or not. */ + /* Stores the context information related to Digest authentication. - The context is per connection. */ + This information is stored in the per server cache in the serf context. */ typedef struct digest_authn_info_t { /* nonce-count for digest authentication */ unsigned int digest_nc; @@ -92,8 +96,9 @@ return hex_encode((unsigned char*)buf, pool); } -static const char * -build_digest_ha1(const char *username, +static apr_status_t +build_digest_ha1(const char **out_ha1, + const char *username, const char *password, const char *realm_name, apr_pool_t *pool) @@ -109,12 +114,17 @@ realm_name, password); status = apr_md5(ha1, tmp, strlen(tmp)); + if (status) + return status; - return hex_encode(ha1, pool); + *out_ha1 = hex_encode(ha1, pool); + + return APR_SUCCESS; } -static const char * -build_digest_ha2(const char *uri, +static apr_status_t +build_digest_ha2(const char **out_ha2, + const char *uri, const char *method, const char *qop, apr_pool_t *pool) @@ -130,17 +140,21 @@ method, uri); status = apr_md5(ha2, tmp, strlen(tmp)); + if (status) + return status; + + *out_ha2 = hex_encode(ha2, pool); - return hex_encode(ha2, pool); + return APR_SUCCESS; } else { /* TODO: auth-int isn't supported! */ + return APR_ENOTIMPL; } - - return NULL; } -static const char * -build_auth_header(digest_authn_info_t *digest_info, +static apr_status_t +build_auth_header(const char **out_header, + digest_authn_info_t *digest_info, const char *path, const char *method, apr_pool_t *pool) @@ -152,7 +166,9 @@ const char *response_hdr_hex; apr_status_t status; - ha2 = build_digest_ha2(path, method, digest_info->qop, pool); + status = build_digest_ha2(&ha2, path, method, digest_info->qop, pool); + if (status) + return status; hdr = apr_psprintf(pool, "Digest realm=\"%s\"," @@ -190,6 +206,9 @@ } status = apr_md5(response_hdr, response, strlen(response)); + if (status) + return status; + response_hdr_hex = hex_encode(response_hdr, pool); hdr = apr_psprintf(pool, "%s, response=\"%s\"", hdr, response_hdr_hex); @@ -203,7 +222,9 @@ digest_info->algorithm); } - return hdr; + *out_header = hdr; + + return APR_SUCCESS; } apr_status_t @@ -217,7 +238,7 @@ { char *attrs; char *nextkv; - const char *realm_name = NULL; + const char *realm, *realm_name = NULL; const char *nonce = NULL; const char *algorithm = NULL; const char *qop = NULL; @@ -225,10 +246,8 @@ const char *key; serf_connection_t *conn = request->conn; serf_context_t *ctx = conn->ctx; - serf__authn_info_t *authn_info = (code == 401) ? &ctx->authn_info : - &ctx->proxy_authn_info; - digest_authn_info_t *digest_info = (code == 401) ? conn->authn_baton : - conn->proxy_authn_baton; + serf__authn_info_t *authn_info; + digest_authn_info_t *digest_info; apr_status_t status; apr_pool_t *cred_pool; char *username, *password; @@ -239,6 +258,13 @@ return SERF_ERROR_AUTHN_FAILED; } + if (code == 401) { + authn_info = serf__get_authn_info_for_server(conn); + } else { + authn_info = &ctx->proxy_authn_info; + } + digest_info = authn_info->baton; + /* Need a copy cuz we're going to write NUL characters into the string. */ attrs = apr_pstrdup(pool, auth_attr); @@ -286,17 +312,17 @@ return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE; } - authn_info->realm = apr_psprintf(conn->pool, "<%s://%s:%d> %s", - conn->host_info.scheme, - conn->host_info.hostname, - conn->host_info.port, - realm_name); + realm = serf__construct_realm(code == 401 ? HOST : PROXY, + conn, realm_name, + pool); /* Ask the application for credentials */ apr_pool_create(&cred_pool, pool); - status = (*ctx->cred_cb)(&username, &password, request, baton, - code, authn_info->scheme->name, - authn_info->realm, cred_pool); + status = serf__provide_credentials(ctx, + &username, &password, + request, baton, + code, authn_info->scheme->name, + realm, cred_pool); if (status) { apr_pool_destroy(cred_pool); return status; @@ -305,9 +331,12 @@ digest_info->header = (code == 401) ? "Authorization" : "Proxy-Authorization"; - /* Store the digest authentication parameters in the context relative - to this connection, so we can use it to create the Authorization header - when setting up requests. */ + /* Store the digest authentication parameters in the context cached for + this server in the serf context, so we can use it to create the + Authorization header when setting up requests on the same or different + connections (e.g. in case of KeepAlive off on the server). + TODO: we currently don't cache this info per realm, so each time a request + 'switches realms', we have to ask the application for new credentials. */ digest_info->pool = conn->pool; digest_info->qop = apr_pstrdup(digest_info->pool, qop); digest_info->nonce = apr_pstrdup(digest_info->pool, nonce); @@ -318,8 +347,8 @@ digest_info->username = apr_pstrdup(digest_info->pool, username); digest_info->digest_nc++; - digest_info->ha1 = build_digest_ha1(username, password, digest_info->realm, - digest_info->pool); + status = build_digest_ha1(&digest_info->ha1, username, password, + digest_info->realm, digest_info->pool); apr_pool_destroy(cred_pool); @@ -327,7 +356,7 @@ likes. */ serf_connection_set_max_outstanding_requests(conn, 0); - return APR_SUCCESS; + return status; } apr_status_t @@ -339,16 +368,22 @@ } apr_status_t -serf__init_digest_connection(int code, +serf__init_digest_connection(const serf__authn_scheme_t *scheme, + int code, serf_connection_t *conn, apr_pool_t *pool) { - /* Digest authentication is done per connection, so keep all progress - information per connection. */ + serf_context_t *ctx = conn->ctx; + serf__authn_info_t *authn_info; + if (code == 401) { - conn->authn_baton = apr_pcalloc(pool, sizeof(digest_authn_info_t)); + authn_info = serf__get_authn_info_for_server(conn); } else { - conn->proxy_authn_baton = apr_pcalloc(pool, sizeof(digest_authn_info_t)); + authn_info = &ctx->proxy_authn_info; + } + + if (!authn_info->baton) { + authn_info->baton = apr_pcalloc(pool, sizeof(digest_authn_info_t)); } /* Make serf send the initial requests one by one */ @@ -358,39 +393,73 @@ } apr_status_t -serf__setup_request_digest_auth(int code, +serf__setup_request_digest_auth(peer_t peer, + int code, serf_connection_t *conn, + serf_request_t *request, const char *method, const char *uri, serf_bucket_t *hdrs_bkt) { - digest_authn_info_t *digest_info = (code == 401) ? conn->authn_baton : - conn->proxy_authn_baton; - apr_status_t status = APR_SUCCESS; + serf_context_t *ctx = conn->ctx; + serf__authn_info_t *authn_info; + digest_authn_info_t *digest_info; + apr_status_t status; + + if (peer == HOST) { + authn_info = serf__get_authn_info_for_server(conn); + } else { + authn_info = &ctx->proxy_authn_info; + } + digest_info = authn_info->baton; if (digest_info && digest_info->realm) { const char *value; - apr_uri_t parsed_uri; + const char *path; - /* extract path from uri */ - status = apr_uri_parse(conn->pool, uri, &parsed_uri); + /* TODO: per request pool? */ + + /* for request 'CONNECT serf.googlecode.com:443', the uri also should be + serf.googlecode.com:443. apr_uri_parse can't handle this, so special + case. */ + if (strcmp(method, "CONNECT") == 0) + path = uri; + else { + apr_uri_t parsed_uri; + + /* Extract path from uri. */ + status = apr_uri_parse(conn->pool, uri, &parsed_uri); + if (status) + return status; + + path = parsed_uri.path; + } /* Build a new Authorization header. */ - digest_info->header = (code == 401) ? "Authorization" : + digest_info->header = (peer == HOST) ? "Authorization" : "Proxy-Authorization"; - value = build_auth_header(digest_info, parsed_uri.path, method, - conn->pool); + status = build_auth_header(&value, digest_info, path, method, + conn->pool); + if (status) + return status; serf_bucket_headers_setn(hdrs_bkt, digest_info->header, value); digest_info->digest_nc++; + + /* Store the uri of this request on the serf_request_t object, to make + it available when validating the Authentication-Info header of the + matching response. */ + request->auth_baton = (void *)path; } - return status; + return APR_SUCCESS; } apr_status_t -serf__validate_response_digest_auth(int code, +serf__validate_response_digest_auth(const serf__authn_scheme_t *scheme, + peer_t peer, + int code, serf_connection_t *conn, serf_request_t *request, serf_bucket_t *response, @@ -403,13 +472,13 @@ const char *qop = NULL; const char *nc_str = NULL; serf_bucket_t *hdrs; - digest_authn_info_t *digest_info = (code == 401) ? conn->authn_baton : - conn->proxy_authn_baton; + serf_context_t *ctx = conn->ctx; + apr_status_t status; hdrs = serf_bucket_response_get_headers(response); /* Need a copy cuz we're going to write NUL characters into the string. */ - if (code == 401) + if (peer == HOST) auth_attr = apr_pstrdup(pool, serf_bucket_headers_get(hdrs, "Authentication-Info")); else @@ -457,8 +526,21 @@ if (rspauth) { const char *ha2, *tmp, *resp_hdr_hex; unsigned char resp_hdr[APR_MD5_DIGESTSIZE]; + const char *req_uri = request->auth_baton; + serf__authn_info_t *authn_info; + digest_authn_info_t *digest_info; + + if (peer == HOST) { + authn_info = serf__get_authn_info_for_server(conn); + } else { + authn_info = &ctx->proxy_authn_info; + } + digest_info = authn_info->baton; + + status = build_digest_ha2(&ha2, req_uri, "", qop, pool); + if (status) + return status; - ha2 = build_digest_ha2(conn->host_info.path, "", qop, pool); tmp = apr_psprintf(pool, "%s:%s:%s:%s:%s:%s", digest_info->ha1, digest_info->nonce, nc_str, digest_info->cnonce, digest_info->qop, ha2); diff -Nru serf-1.1.0/auth/auth_kerb.c serf-1.3.3/auth/auth_kerb.c --- serf-1.1.0/auth/auth_kerb.c 2010-03-21 20:22:24.000000000 +0000 +++ serf-1.3.3/auth/auth_kerb.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,350 +0,0 @@ -/* Copyright 2009 Justin Erenkrantz and Greg Stein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "auth_kerb.h" - -#ifdef SERF_HAVE_KERB - -/*** Kerberos authentication ***/ - -#include -#include -#include - -#include -#include -#include - -/** These functions implements Kerberos authentication, using GSS-API - * (RFC 2743). The message-exchange is documented in RFC 4559. - * - * Note: this implementation uses gssapi and only works on *nix. - **/ - -/** TODO: - ** - send session key directly on new connections where we already know - ** the server requires Kerberos authn. - ** - fix authn status, as the COMPLETE/CONTINUE status values - ** are never used. - ** - Add a way for serf to give detailed error information back to the - ** application. - ** - proxy support - **/ - -/* Authentication over HTTP using Kerberos - * - * Kerberos involves three servers: - * - Authentication Server (AS): verifies users during login - * - Ticket-Granting Server (TGS): issues proof of identity tickets - * - HTTP server (S) - * - * Steps: - * 0. User logs in to the AS and receives a TGS ticket. On workstations - * where the login program doesn't support Kerberos, the user can use - * 'kinit'. - * - * 1. C --> S: GET - * - * C <-- S: 401 Authentication Required - * WWW-Authenticate: Negotiate - * - * -> app contacts the TGS to request a session key for the HTTP service - * @ target host. The returned session key is encrypted with the HTTP - * service's secret key, so we can safely send it to the server. - * - * 2. C --> S: GET - * Authorization: Negotiate - * gss_api_ctx->state = gss_api_auth_in_progress; - * - * C <-- S: 200 OK - * WWW-Authenticate: Negotiate - * - * -> The server returned a key to proof itself to us. We check this key - * with the TGS again. - * - * Note: It's possible that the server returns 401 again in step 3, if the - * Kerberos context isn't complete yet. Some (simple) tests with - * mod_auth_kerb and MIT Kerberos 5 show this never happens. - * - * This handshake is required for every new connection. If the handshake is - * completed successfully, all other requests on the same connection will - * be authenticated without needing to pass the WWW-Authenticate header. - * - * Note: Step 1 of the handshake will only happen on the first connection, once - * we know the server requires Kerberos authentication, the initial requests - * on the other connections will include a session key, so we start at - * step 2 in the handshake. - * ### TODO: Not implemented yet! - */ - -typedef enum { - gss_api_auth_not_started, - gss_api_auth_in_progress, - gss_api_auth_completed, -} gss_api_auth_state; - -/* HTTP Service name, used to get the session key. */ -#define KRB_HTTP_SERVICE "HTTP" - -/* Stores the context information related to Kerberos authentication. */ -typedef struct -{ - apr_pool_t *pool; - - /* GSSAPI context */ - serf__kerb_context_t *gss_ctx; - - /* Current state of the authentication cycle. */ - gss_api_auth_state state; - - const char *header; - const char *value; -} gss_authn_info_t; - -/* On the initial 401 response of the server, request a session key from - the Kerberos KDC to pass to the server, proving that we are who we - claim to be. The session key can only be used with the HTTP service - on the target host. */ -static apr_status_t -gss_api_get_credentials(char *token, apr_size_t token_len, - const char *hostname, - const char **buf, apr_size_t *buf_len, - gss_authn_info_t *gss_info) -{ - serf__kerb_buffer_t input_buf; - serf__kerb_buffer_t output_buf; - apr_status_t status = APR_SUCCESS; - - /* If the server sent us a token, pass it to gss_init_sec_token for - validation. */ - if (token) { - input_buf.value = token; - input_buf.length = token_len; - } else { - input_buf.value = 0; - input_buf.length = 0; - } - - /* Establish a security context to the server. */ - status = serf__kerb_init_sec_context - (gss_info->gss_ctx, - KRB_HTTP_SERVICE, hostname, - &input_buf, - &output_buf, - gss_info->pool, - gss_info->pool - ); - - switch(status) { - case APR_SUCCESS: - gss_info->state = gss_api_auth_completed; - break; - case APR_EAGAIN: - gss_info->state = gss_api_auth_in_progress; - status = APR_SUCCESS; - break; - default: - status = SERF_ERROR_AUTHN_FAILED; - break; - } - - /* Return the session key to our caller. */ - *buf = output_buf.value; - *buf_len = output_buf.length; - - return status; -} - -/* Read the header sent by the server (if any), invoke the gssapi authn - code and use the resulting Server Ticket on the next request to the - server. */ -static apr_status_t -do_auth(int code, - gss_authn_info_t *gss_info, - serf_connection_t *conn, - const char *auth_hdr, - apr_pool_t *pool) -{ - serf_context_t *ctx = conn->ctx; - serf__authn_info_t *authn_info = (code == 401) ? &ctx->authn_info : - &ctx->proxy_authn_info; - const char *tmp = NULL; - char *token = NULL; - apr_size_t tmp_len = 0, token_len = 0; - const char *space = NULL; - apr_status_t status; - - /* The server will return a token as attribute to the Negotiate key. - Negotiate YGwGCSqGSIb3EgECAgIAb10wW6ADAgEFoQMCAQ+iTzBNoAMCARCiRgREa6mouM - BAMFqKVdTGtfpZNXKzyw4Yo1paphJdIA3VOgncaoIlXxZLnkHiIHS2v65pVvrp - bRIyjF8xve9HxpnNIucCY9c= - - Read this base64 value, decode it and validate it so we're sure the server - is who we expect it to be. */ - if (auth_hdr) - space = strchr(auth_hdr, ' '); - - if (space) { - token = apr_palloc(pool, apr_base64_decode_len(space + 1)); - token_len = apr_base64_decode(token, space + 1); - } - - /* We can get a whole batch of 401 responses from the server, but we should - only start the authentication phase once, so if we started authentication - already ignore all responses with initial Negotiate authentication header. - - Note: as we set the max. transfer rate to one message at a time until the - authentication cycle is finished, this check shouldn't be needed. */ - if (!token && gss_info->state != gss_api_auth_not_started) - return APR_SUCCESS; - - status = gss_api_get_credentials(token, token_len, conn->host_info.hostname, - &tmp, &tmp_len, - gss_info); - if (status) - return status; - - serf__encode_auth_header(&gss_info->value, authn_info->scheme->name, - tmp, - tmp_len, - pool); - gss_info->header = (code == 401) ? "Authorization" : "Proxy-Authorization"; - - /* If the handshake is finished tell serf it can send as much requests as it - likes. */ - if (gss_info->state == gss_api_auth_completed) - serf_connection_set_max_outstanding_requests(conn, 0); - - return APR_SUCCESS; -} - -apr_status_t -serf__init_kerb(int code, - serf_context_t *ctx, - apr_pool_t *pool) -{ - return APR_SUCCESS; -} - -/* A new connection is created to a server that's known to use - Kerberos. */ -apr_status_t -serf__init_kerb_connection(int code, - serf_connection_t *conn, - apr_pool_t *pool) -{ - gss_authn_info_t *gss_info; - apr_status_t status; - - gss_info = apr_pcalloc(pool, sizeof(*gss_info)); - gss_info->pool = conn->pool; - gss_info->state = gss_api_auth_not_started; - status = serf__kerb_create_sec_context(&gss_info->gss_ctx, pool, - gss_info->pool); - - if (status) { - return status; - } - - if (code == 401) { - conn->authn_baton = gss_info; - } else { - conn->proxy_authn_baton = gss_info; - } - - /* Make serf send the initial requests one by one */ - serf_connection_set_max_outstanding_requests(conn, 1); - - return APR_SUCCESS; -} - -/* A 401 response was received, handle the authentication. */ -apr_status_t -serf__handle_kerb_auth(int code, - serf_request_t *request, - serf_bucket_t *response, - const char *auth_hdr, - const char *auth_attr, - void *baton, - apr_pool_t *pool) -{ - serf_connection_t *conn = request->conn; - gss_authn_info_t *gss_info = (code == 401) ? conn->authn_baton : - conn->proxy_authn_baton; - - return do_auth(code, - gss_info, - request->conn, - auth_hdr, - pool); -} - -/* Setup the authn headers on this request message. */ -apr_status_t -serf__setup_request_kerb_auth(int code, - serf_connection_t *conn, - const char *method, - const char *uri, - serf_bucket_t *hdrs_bkt) -{ - gss_authn_info_t *gss_info = (code == 401) ? conn->authn_baton : - conn->proxy_authn_baton; - - if (gss_info && gss_info->header && gss_info->value) { - serf_bucket_headers_setn(hdrs_bkt, gss_info->header, - gss_info->value); - - /* We should send each token only once. */ - gss_info->header = NULL; - gss_info->value = NULL; - return APR_SUCCESS; - } - - return SERF_ERROR_AUTHN_FAILED; -} - -/* Function is called when 2xx responses are received. Normally we don't - * have to do anything, except for the first response after the - * authentication handshake. This specific response includes authentication - * data which should be validated by the client (mutual authentication). - */ -apr_status_t -serf__validate_response_kerb_auth(int code, - serf_connection_t *conn, - serf_request_t *request, - serf_bucket_t *response, - apr_pool_t *pool) -{ - gss_authn_info_t *gss_info = (code == 401) ? conn->authn_baton : - conn->proxy_authn_baton; - serf_bucket_t *hdrs; - const char *auth_hdr; - - hdrs = serf_bucket_response_get_headers(response); - auth_hdr = serf_bucket_headers_get(hdrs, "WWW-Authenticate"); - - if (gss_info->state != gss_api_auth_completed) { - return do_auth(code, - gss_info, - conn, - auth_hdr, - pool); - } - - return APR_SUCCESS; -} - -#endif /* SERF_HAVE_GSSAPI */ diff -Nru serf-1.1.0/auth/auth_kerb.h serf-1.3.3/auth/auth_kerb.h --- serf-1.1.0/auth/auth_kerb.h 2010-05-13 17:17:12.000000000 +0000 +++ serf-1.3.3/auth/auth_kerb.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,103 +0,0 @@ -/* Copyright 2010 Justin Erenkrantz and Greg Stein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef AUTH_KERB_H -#define AUTH_KERB_H - -#include -#include - -#if defined(SERF_HAVE_SSPI) -#define SERF_HAVE_KERB -#define SERF_USE_SSPI -#elif defined(SERF_HAVE_GSSAPI) -#define SERF_HAVE_KERB -#define SERF_USE_GSSAPI -#endif - -#ifdef SERF_HAVE_KERB - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct serf__kerb_context_t serf__kerb_context_t; - -typedef struct serf__kerb_buffer_t { - apr_size_t length; - void *value; -} serf__kerb_buffer_t; - -/* Create outbound security context. - * - * All temporary allocations will be performed in SCRATCH_POOL, while security - * context will be allocated in result_pool and will be destroyed automatically - * on RESULT_POOL cleanup. - * - */ -apr_status_t -serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p, - apr_pool_t *scratch_pool, - apr_pool_t *result_pool); - -/* Initialize outbound security context. - * - * The function is used to build a security context between the client - * application and a remote peer. - * - * CTX is pointer to existing context created using - * serf__kerb_create_sec_context() function. - * - * SERVICE is name of Kerberos service name. Usually 'HTTP'. HOSTNAME is - * canonical name of destination server. Caller should resolve server's alias - * to canonical name. - * - * INPUT_BUF is pointer structure describing input token if any. Should be - * zero length on first call. - * - * OUTPUT_BUF will be populated with pointer to output data that should send - * to destination server. This buffer will be automatically freed on - * RESULT_POOL cleanup. - * - * All temporary allocations will be performed in SCRATCH_POOL. - * - * Return value: - * - APR_EAGAIN The client must send the output token to the server and wait - * for a return token. - * - * - APR_SUCCESS The security context was successfully initialized. There is no - * need for another serf__kerb_init_sec_context call. If the function returns - * an output token, that is, if the OUTPUT_BUF is of nonzero length, that - * token must be sent to the server. - * - * Other returns values indicates error. - */ -apr_status_t -serf__kerb_init_sec_context(serf__kerb_context_t *ctx, - const char *service, - const char *hostname, - serf__kerb_buffer_t *input_buf, - serf__kerb_buffer_t *output_buf, - apr_pool_t *scratch_pool, - apr_pool_t *result_pool - ); - -#ifdef __cplusplus -} -#endif - -#endif /* SERF_HAVE_KERB */ - -#endif /* !AUTH_KERB_H */ diff -Nru serf-1.1.0/auth/auth_kerb_gss.c serf-1.3.3/auth/auth_kerb_gss.c --- serf-1.1.0/auth/auth_kerb_gss.c 2010-05-13 17:17:12.000000000 +0000 +++ serf-1.3.3/auth/auth_kerb_gss.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -/* Copyright 2009 Justin Erenkrantz and Greg Stein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "auth_kerb.h" - -#ifdef SERF_USE_GSSAPI -#include -#include - -struct serf__kerb_context_t -{ - /* GSSAPI context */ - gss_ctx_id_t gss_ctx; - - /* Mechanism used to authenticate, should be Kerberos. */ - gss_OID gss_mech; -}; - -/* Cleans the GSS context object, when the pool used to create it gets - cleared or destroyed. */ -static apr_status_t -cleanup_ctx(void *data) -{ - OM_uint32 min_stat; - serf__kerb_context_t *ctx = data; - - if (ctx->gss_ctx != GSS_C_NO_CONTEXT) { - if (gss_delete_sec_context(&min_stat, &ctx->gss_ctx, - GSS_C_NO_BUFFER) == GSS_S_FAILURE) - return APR_EGENERAL; - } - - return APR_SUCCESS; -} - -static apr_status_t -cleanup_sec_buffer(void *data) -{ - OM_uint32 min_stat; - gss_buffer_desc *gss_buf = data; - - gss_release_buffer(&min_stat, gss_buf); - - return APR_SUCCESS; -} - -apr_status_t -serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p, - apr_pool_t *scratch_pool, - apr_pool_t *result_pool) -{ - serf__kerb_context_t *ctx; - - ctx = apr_pcalloc(result_pool, sizeof(*ctx)); - - ctx->gss_ctx = GSS_C_NO_CONTEXT; - ctx->gss_mech = GSS_C_NO_OID; - - apr_pool_cleanup_register(result_pool, ctx, - cleanup_ctx, - apr_pool_cleanup_null); - - *ctx_p = ctx; - - return APR_SUCCESS; -} - -apr_status_t -serf__kerb_init_sec_context(serf__kerb_context_t *ctx, - const char *service, - const char *hostname, - serf__kerb_buffer_t *input_buf, - serf__kerb_buffer_t *output_buf, - apr_pool_t *scratch_pool, - apr_pool_t *result_pool - ) -{ - gss_buffer_desc gss_input_buf = GSS_C_EMPTY_BUFFER; - gss_buffer_desc *gss_output_buf_p; - OM_uint32 gss_min_stat, gss_maj_stat; - gss_name_t host_gss_name; - gss_buffer_desc bufdesc; - - /* Get the name for the HTTP service at the target host. */ - bufdesc.value = apr_pstrcat(scratch_pool, service, "@", hostname, NULL); - bufdesc.length = strlen(bufdesc.value); - gss_maj_stat = gss_import_name (&gss_min_stat, &bufdesc, GSS_C_NT_HOSTBASED_SERVICE, - &host_gss_name); - if(GSS_ERROR(gss_maj_stat)) { - return APR_EGENERAL; - } - - /* If the server sent us a token, pass it to gss_init_sec_token for - validation. */ - gss_input_buf.value = input_buf->value; - gss_input_buf.length = input_buf->length; - - gss_output_buf_p = apr_pcalloc(result_pool, sizeof(*gss_output_buf_p)); - - /* Establish a security context to the server. */ - gss_maj_stat = gss_init_sec_context - (&gss_min_stat, /* minor_status */ - GSS_C_NO_CREDENTIAL, /* XXXXX claimant_cred_handle */ - &ctx->gss_ctx, /* gssapi context handle */ - host_gss_name, /* HTTP@server name */ - ctx->gss_mech, /* mech_type (0 ininitially */ - GSS_C_MUTUAL_FLAG, /* ensure the peer authenticates itself */ - 0, /* default validity period */ - GSS_C_NO_CHANNEL_BINDINGS, /* do not use channel bindings */ - &gss_input_buf, /* server token, initially empty */ - &ctx->gss_mech, /* actual mech type */ - gss_output_buf_p, /* output_token */ - NULL, /* ret_flags */ - NULL /* not interested in remaining validity */ - ); - - apr_pool_cleanup_register(result_pool, gss_output_buf_p, - cleanup_sec_buffer, - apr_pool_cleanup_null); - - output_buf->value = gss_output_buf_p->value; - output_buf->length = gss_output_buf_p->length; - - switch(gss_maj_stat) { - case GSS_S_COMPLETE: - return APR_SUCCESS; - case GSS_S_CONTINUE_NEEDED: - return APR_EAGAIN; - default: - return APR_EGENERAL; - } -} - -#endif /* SERF_USE_GSSAPI */ diff -Nru serf-1.1.0/auth/auth_kerb_sspi.c serf-1.3.3/auth/auth_kerb_sspi.c --- serf-1.1.0/auth/auth_kerb_sspi.c 2011-03-18 15:40:54.000000000 +0000 +++ serf-1.3.3/auth/auth_kerb_sspi.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,210 +0,0 @@ -/* Copyright 2010 Justin Erenkrantz and Greg Stein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "auth_kerb.h" - -#ifdef SERF_USE_SSPI -#include -#include - -#define SECURITY_WIN32 -#include - -struct serf__kerb_context_t -{ - CredHandle sspi_credentials; - CtxtHandle sspi_context; - BOOL initalized; -}; - -/* Cleans the SSPI context object, when the pool used to create it gets - cleared or destroyed. */ -static apr_status_t -cleanup_ctx(void *data) -{ - serf__kerb_context_t *ctx = data; - - if (SecIsValidHandle(&ctx->sspi_context)) { - DeleteSecurityContext(&ctx->sspi_context); - SecInvalidateHandle(&ctx->sspi_context); - } - - if (SecIsValidHandle(&ctx->sspi_credentials)) { - FreeCredentialsHandle(&ctx->sspi_context); - SecInvalidateHandle(&ctx->sspi_context); - } - - return APR_SUCCESS; -} - -static apr_status_t -cleanup_sec_buffer(void *data) -{ - FreeContextBuffer(data); - - return APR_SUCCESS; -} - -apr_status_t -serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p, - apr_pool_t *scratch_pool, - apr_pool_t *result_pool) -{ - SECURITY_STATUS sspi_status; - serf__kerb_context_t *ctx; - - ctx = apr_pcalloc(result_pool, sizeof(*ctx)); - - SecInvalidateHandle(&ctx->sspi_context); - SecInvalidateHandle(&ctx->sspi_credentials); - ctx->initalized = FALSE; - - apr_pool_cleanup_register(result_pool, ctx, - cleanup_ctx, - apr_pool_cleanup_null); - - sspi_status = AcquireCredentialsHandle( - NULL, "Negotiate", SECPKG_CRED_OUTBOUND, - NULL, NULL, NULL, NULL, - &ctx->sspi_credentials, NULL); - - if (FAILED(sspi_status)) { - return APR_EGENERAL; - } - - *ctx_p = ctx; - - return APR_SUCCESS; -} - -static apr_status_t -get_canonical_hostname(const char **canonname, - const char *hostname, - apr_pool_t *pool) -{ - struct addrinfo hints; - struct addrinfo *addrinfo; - - ZeroMemory(&hints, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - - if (getaddrinfo(hostname, NULL, &hints, &addrinfo)) { - return apr_get_netos_error(); - } - - if (addrinfo) { - *canonname = apr_pstrdup(pool, addrinfo->ai_canonname); - } - else { - *canonname = apr_pstrdup(pool, hostname); - } - - freeaddrinfo(addrinfo); - return APR_SUCCESS; -} - -apr_status_t -serf__kerb_init_sec_context(serf__kerb_context_t *ctx, - const char *service, - const char *hostname, - serf__kerb_buffer_t *input_buf, - serf__kerb_buffer_t *output_buf, - apr_pool_t *scratch_pool, - apr_pool_t *result_pool - ) -{ - SECURITY_STATUS status; - ULONG actual_attr; - SecBuffer sspi_in_buffer; - SecBufferDesc sspi_in_buffer_desc; - SecBuffer sspi_out_buffer; - SecBufferDesc sspi_out_buffer_desc; - char *target_name; - apr_status_t apr_status; - const char *canonname; - - apr_status = get_canonical_hostname(&canonname, hostname, scratch_pool); - if (apr_status) { - return apr_status; - } - target_name = apr_pstrcat(scratch_pool, service, "/", canonname, NULL); - - /* Prepare input buffer description. */ - sspi_in_buffer.BufferType = SECBUFFER_TOKEN; - sspi_in_buffer.pvBuffer = input_buf->value; - sspi_in_buffer.cbBuffer = input_buf->length; - - sspi_in_buffer_desc.cBuffers = 1; - sspi_in_buffer_desc.pBuffers = &sspi_in_buffer; - sspi_in_buffer_desc.ulVersion = SECBUFFER_VERSION; - - /* Output buffers. Output buffer will be allocated by system. */ - sspi_out_buffer.BufferType = SECBUFFER_TOKEN; - sspi_out_buffer.pvBuffer = NULL; - sspi_out_buffer.cbBuffer = 0; - - sspi_out_buffer_desc.cBuffers = 1; - sspi_out_buffer_desc.pBuffers = &sspi_out_buffer; - sspi_out_buffer_desc.ulVersion = SECBUFFER_VERSION; - - status = InitializeSecurityContext( - &ctx->sspi_credentials, - ctx->initalized ? &ctx->sspi_context : NULL, - target_name, - ISC_REQ_ALLOCATE_MEMORY - | ISC_REQ_MUTUAL_AUTH - | ISC_REQ_CONFIDENTIALITY, - 0, /* Reserved1 */ - SECURITY_NETWORK_DREP, - &sspi_in_buffer_desc, - 0, /* Reserved2 */ - &ctx->sspi_context, - &sspi_out_buffer_desc, - &actual_attr, - NULL); - - if (sspi_out_buffer.cbBuffer > 0) { - apr_pool_cleanup_register(result_pool, sspi_out_buffer.pvBuffer, - cleanup_sec_buffer, - apr_pool_cleanup_null); - } - - ctx->initalized = TRUE; - - /* Finish authentication if SSPI requires so. */ - if (status == SEC_I_COMPLETE_NEEDED - || status == SEC_I_COMPLETE_AND_CONTINUE) - { - CompleteAuthToken(&ctx->sspi_context, &sspi_out_buffer_desc); - } - - output_buf->value = sspi_out_buffer.pvBuffer; - output_buf->length = sspi_out_buffer.cbBuffer; - - switch(status) { - case SEC_I_COMPLETE_AND_CONTINUE: - case SEC_I_CONTINUE_NEEDED: - return APR_EAGAIN; - - case SEC_I_COMPLETE_NEEDED: - case SEC_E_OK: - return APR_SUCCESS; - - default: - return APR_EGENERAL; - } -} - -#endif /* SERF_USE_SSPI */ \ No newline at end of file diff -Nru serf-1.1.0/auth/auth_spnego.c serf-1.3.3/auth/auth_spnego.c --- serf-1.1.0/auth/auth_spnego.c 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/auth/auth_spnego.c 2013-08-15 09:00:57.000000000 +0000 @@ -0,0 +1,642 @@ +/* Copyright 2009 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_spnego.h" + +#ifdef SERF_HAVE_SPNEGO + +/** These functions implement SPNEGO-based Kerberos and NTLM authentication, + * using either GSS-API (RFC 2743) or SSPI on Windows. + * The HTTP message exchange is documented in RFC 4559. + **/ + +#include +#include +#include + +#include +#include +#include + +/** TODO: + ** - send session key directly on new connections where we already know + ** the server requires Kerberos authn. + ** - Add a way for serf to give detailed error information back to the + ** application. + **/ + +/* Authentication over HTTP using Kerberos + * + * Kerberos involves three servers: + * - Authentication Server (AS): verifies users during login + * - Ticket-Granting Server (TGS): issues proof of identity tickets + * - HTTP server (S) + * + * Steps: + * 0. User logs in to the AS and receives a TGS ticket. On workstations + * where the login program doesn't support Kerberos, the user can use + * 'kinit'. + * + * 1. C --> S: GET + * + * C <-- S: 401 Authentication Required + * WWW-Authenticate: Negotiate + * + * -> app contacts the TGS to request a session key for the HTTP service + * @ target host. The returned session key is encrypted with the HTTP + * service's secret key, so we can safely send it to the server. + * + * 2. C --> S: GET + * Authorization: Negotiate + * gss_api_ctx->state = gss_api_auth_in_progress; + * + * C <-- S: 200 OK + * WWW-Authenticate: Negotiate + * + * -> The server returned an (optional) key to proof itself to us. We check this + * key with the TGS again. If it checks out, we can return the response + * body to the application. + * + * Note: It's possible that the server returns 401 again in step 2, if the + * Kerberos context isn't complete yet. This means there is 3rd step + * where we'll send a request with an Authorization header to the + * server. Some (simple) tests with mod_auth_kerb and MIT Kerberos 5 show + * this never happens. + * + * Depending on the type of HTTP server, this handshake is required for either + * every new connection, or for every new request! For more info see the next + * comment on authn_persistence_state_t. + * + * Note: Step 1 of the handshake will only happen on the first connection, once + * we know the server requires Kerberos authentication, the initial requests + * on the other connections will include a session key, so we start at + * step 2 in the handshake. + * ### TODO: Not implemented yet! + */ + +/* Current state of the authentication of the current request. */ +typedef enum { + gss_api_auth_not_started, + gss_api_auth_in_progress, + gss_api_auth_completed, +} gss_api_auth_state; + +/** + authn_persistence_state_t: state that indicates if we are talking with a + server that requires authentication only of the first request (stateful), + or of each request (stateless). + + INIT: Begin state. Authenticating the first request on this connection. + UNDECIDED: we haven't identified the server yet, assume STATEFUL for now. + Pipeline mode disabled, requests are sent only after the response off the + previous request arrived. + STATELESS: we know the server requires authentication for each request. + On all new requests add the Authorization header with an initial SPNEGO + token (created per request). + To keep things simple, keep the connection in one by one mode. + (otherwise we'd have to keep a queue of gssapi context objects to match + the Negotiate header of the response with the session initiated by the + mathing request). + This state is an final state. + STATEFUL: alright, we have authenticated the connection and for the server + that is enough. Don't add an Authorization header to new requests. + Serf will switch to pipelined mode. + This state is not a final state, although in practical scenario's it will + be. When we receive a 40x response from the server switch to STATELESS + mode. + + We start in state init for the first request until it is authenticated. + + The rest of the state machine starts with the arrival of the response to the + second request, and then goes on with each response: + + -------- + | INIT | C --> S: GET request in response to 40x of the server + -------- add [Proxy]-Authorization header + | + | + ------------ + | UNDECIDED| C --> S: GET request, assume stateful, + ------------ no [Proxy]-Authorization header + | + | + |------------------------------------------------ + | | + | C <-- S: 40x Authentication | C <-- S: 200 OK + | Required | + | | + v v + ------------- ------------ + ->| STATELESS |<------------------------------| STATEFUL |<-- + | ------------- C <-- S: 40x ------------ | + * | | Authentication | | 200 OK + | / Required | | + ----- -----/ + + **/ +typedef enum { + pstate_init, + pstate_undecided, + pstate_stateless, + pstate_stateful, +} authn_persistence_state_t; + + +/* HTTP Service name, used to get the session key. */ +#define KRB_HTTP_SERVICE "HTTP" + +/* Stores the context information related to Kerberos authentication. */ +typedef struct +{ + apr_pool_t *pool; + + /* GSSAPI context */ + serf__spnego_context_t *gss_ctx; + + /* Current state of the authentication cycle. */ + gss_api_auth_state state; + + /* Current persistence state. */ + authn_persistence_state_t pstate; + + const char *header; + const char *value; +} gss_authn_info_t; + +/* On the initial 401 response of the server, request a session key from + the Kerberos KDC to pass to the server, proving that we are who we + claim to be. The session key can only be used with the HTTP service + on the target host. */ +static apr_status_t +gss_api_get_credentials(char *token, apr_size_t token_len, + const char *hostname, + const char **buf, apr_size_t *buf_len, + gss_authn_info_t *gss_info) +{ + serf__spnego_buffer_t input_buf; + serf__spnego_buffer_t output_buf; + apr_status_t status = APR_SUCCESS; + + /* If the server sent us a token, pass it to gss_init_sec_token for + validation. */ + if (token) { + input_buf.value = token; + input_buf.length = token_len; + } else { + input_buf.value = 0; + input_buf.length = 0; + } + + /* Establish a security context to the server. */ + status = serf__spnego_init_sec_context( + gss_info->gss_ctx, + KRB_HTTP_SERVICE, hostname, + &input_buf, + &output_buf, + gss_info->pool, + gss_info->pool + ); + + switch(status) { + case APR_SUCCESS: + if (output_buf.length == 0) { + gss_info->state = gss_api_auth_completed; + } else { + gss_info->state = gss_api_auth_in_progress; + } + break; + case APR_EAGAIN: + gss_info->state = gss_api_auth_in_progress; + status = APR_SUCCESS; + break; + default: + return status; + } + + /* Return the session key to our caller. */ + *buf = output_buf.value; + *buf_len = output_buf.length; + + return status; +} + +/* do_auth is invoked in two situations: + - when a response from a server is received that contains an authn header + (either from a 40x or 2xx response) + - when a request is prepared on a connection with stateless authentication. + + Read the header sent by the server (if any), invoke the gssapi authn + code and use the resulting Server Ticket on the next request to the + server. */ +static apr_status_t +do_auth(peer_t peer, + int code, + gss_authn_info_t *gss_info, + serf_connection_t *conn, + serf_request_t *request, + const char *auth_hdr, + apr_pool_t *pool) +{ + serf_context_t *ctx = conn->ctx; + serf__authn_info_t *authn_info; + const char *tmp = NULL; + char *token = NULL; + apr_size_t tmp_len = 0, token_len = 0; + apr_status_t status; + + if (peer == HOST) { + authn_info = serf__get_authn_info_for_server(conn); + } else { + authn_info = &ctx->proxy_authn_info; + } + + /* Is this a response from a host/proxy? auth_hdr should always be set. */ + if (code && auth_hdr) { + const char *space = NULL; + /* The server will return a token as attribute to the Negotiate key. + Negotiate YGwGCSqGSIb3EgECAgIAb10wW6ADAgEFoQMCAQ+iTzBNoAMCARCiRgREa6 + mouMBAMFqKVdTGtfpZNXKzyw4Yo1paphJdIA3VOgncaoIlXxZLnkHiIHS2v65pVvrp + bRIyjF8xve9HxpnNIucCY9c= + + Read this base64 value, decode it and validate it so we're sure the + server is who we expect it to be. */ + space = strchr(auth_hdr, ' '); + + if (space) { + token = apr_palloc(pool, apr_base64_decode_len(space + 1)); + token_len = apr_base64_decode(token, space + 1); + } + } else { + /* This is a new request, not a retry in response to a 40x of the + host/proxy. + Only add the Authorization header if we know the server requires + per-request authentication (stateless). */ + if (gss_info->pstate != pstate_stateless) + return APR_SUCCESS; + } + + switch(gss_info->pstate) { + case pstate_init: + /* Nothing to do here */ + break; + case pstate_undecided: /* Fall through */ + case pstate_stateful: + { + /* Switch to stateless mode, from now on handle authentication + of each request with a new gss context. This is easiest to + manage when sending requests one by one. */ + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "Server requires per-request SPNEGO authn, " + "switching to stateless mode.\n"); + + gss_info->pstate = pstate_stateless; + serf_connection_set_max_outstanding_requests(conn, 1); + break; + } + case pstate_stateless: + /* Nothing to do here */ + break; + } + + if (request->auth_baton && !token) { + /* We provided token with this request, but server responded with empty + authentication header. This means server rejected our credentials. + XXX: Probably we need separate error code for this case like + SERF_ERROR_AUTHN_CREDS_REJECTED? */ + return SERF_ERROR_AUTHN_FAILED; + } + + /* If the server didn't provide us with a token, start with a new initial + step in the SPNEGO authentication. */ + if (!token) { + serf__spnego_reset_sec_context(gss_info->gss_ctx); + gss_info->state = gss_api_auth_not_started; + } + + if (peer == HOST) { + status = gss_api_get_credentials(token, token_len, + conn->host_info.hostname, + &tmp, &tmp_len, + gss_info); + } else { + char *proxy_host; + apr_getnameinfo(&proxy_host, conn->ctx->proxy_address, 0); + status = gss_api_get_credentials(token, token_len, proxy_host, + &tmp, &tmp_len, + gss_info); + } + if (status) + return status; + + /* On the next request, add an Authorization header. */ + if (tmp_len) { + serf__encode_auth_header(&gss_info->value, authn_info->scheme->name, + tmp, + tmp_len, + pool); + gss_info->header = (peer == HOST) ? + "Authorization" : "Proxy-Authorization"; + } + + return APR_SUCCESS; +} + +apr_status_t +serf__init_spnego(int code, + serf_context_t *ctx, + apr_pool_t *pool) +{ + return APR_SUCCESS; +} + +/* A new connection is created to a server that's known to use + Kerberos. */ +apr_status_t +serf__init_spnego_connection(const serf__authn_scheme_t *scheme, + int code, + serf_connection_t *conn, + apr_pool_t *pool) +{ + gss_authn_info_t *gss_info; + apr_status_t status; + + gss_info = apr_pcalloc(conn->pool, sizeof(*gss_info)); + gss_info->pool = conn->pool; + gss_info->state = gss_api_auth_not_started; + gss_info->pstate = pstate_init; + status = serf__spnego_create_sec_context(&gss_info->gss_ctx, scheme, + gss_info->pool, pool); + + if (status) { + return status; + } + + if (code == 401) { + conn->authn_baton = gss_info; + } else { + conn->proxy_authn_baton = gss_info; + } + + /* Make serf send the initial requests one by one */ + serf_connection_set_max_outstanding_requests(conn, 1); + + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "Initialized Kerberos context for this connection.\n"); + + return APR_SUCCESS; +} + +/* A 40x response was received, handle the authentication. */ +apr_status_t +serf__handle_spnego_auth(int code, + serf_request_t *request, + serf_bucket_t *response, + const char *auth_hdr, + const char *auth_attr, + void *baton, + apr_pool_t *pool) +{ + serf_connection_t *conn = request->conn; + gss_authn_info_t *gss_info = (code == 401) ? conn->authn_baton : + conn->proxy_authn_baton; + + return do_auth(code == 401 ? HOST : PROXY, + code, + gss_info, + request->conn, + request, + auth_hdr, + pool); +} + +/* Setup the authn headers on this request message. */ +apr_status_t +serf__setup_request_spnego_auth(peer_t peer, + int code, + serf_connection_t *conn, + serf_request_t *request, + const char *method, + const char *uri, + serf_bucket_t *hdrs_bkt) +{ + gss_authn_info_t *gss_info = (peer == HOST) ? conn->authn_baton : + conn->proxy_authn_baton; + + /* If we have an ongoing authentication handshake, the handler of the + previous response will have created the authn headers for this request + already. */ + if (gss_info && gss_info->header && gss_info->value) { + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "Set Negotiate authn header on retried request.\n"); + + serf_bucket_headers_setn(hdrs_bkt, gss_info->header, + gss_info->value); + + /* Remember that we're using this request for authentication + handshake. */ + request->auth_baton = (void*) TRUE; + + /* We should send each token only once. */ + gss_info->header = NULL; + gss_info->value = NULL; + + return APR_SUCCESS; + } + + switch (gss_info->pstate) { + case pstate_init: + /* We shouldn't normally arrive here, do nothing. */ + break; + case pstate_undecided: /* fall through */ + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "Assume for now that the server supports persistent " + "SPNEGO authentication.\n"); + /* Nothing to do here. */ + break; + case pstate_stateful: + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "SPNEGO on this connection is persistent, " + "don't set authn header on next request.\n"); + /* Nothing to do here. */ + break; + case pstate_stateless: + { + apr_status_t status; + + /* Authentication on this connection is known to be stateless. + Add an initial Negotiate token for the server, to bypass the + 40x response we know we'll otherwise receive. + (RFC 4559 section 4.2) */ + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "Add initial Negotiate header to request.\n"); + + status = do_auth(peer, + code, + gss_info, + conn, + request, + 0l, /* no response authn header */ + conn->pool); + if (status) + return status; + + serf_bucket_headers_setn(hdrs_bkt, gss_info->header, + gss_info->value); + + /* Remember that we're using this request for authentication + handshake. */ + request->auth_baton = (void*) TRUE; + + /* We should send each token only once. */ + gss_info->header = NULL; + gss_info->value = NULL; + break; + } + } + + return APR_SUCCESS; +} + +/** + * Baton passed to the get_auth_header callback function. + */ +typedef struct { + const char *hdr_name; + const char *auth_name; + const char *hdr_value; + apr_pool_t *pool; +} get_auth_header_baton_t; + +static int +get_auth_header_cb(void *baton, + const char *key, + const char *header) +{ + get_auth_header_baton_t *b = baton; + + /* We're only interested in xxxx-Authenticate headers. */ + if (strcasecmp(key, b->hdr_name) != 0) + return 0; + + /* Check if header value starts with interesting auth name. */ + if (strncmp(header, b->auth_name, strlen(b->auth_name)) == 0) { + /* Save interesting header value and stop iteration. */ + b->hdr_value = apr_pstrdup(b->pool, header); + return 1; + } + + return 0; +} + +static const char * +get_auth_header(serf_bucket_t *hdrs, + const char *hdr_name, + const char *auth_name, + apr_pool_t *pool) +{ + get_auth_header_baton_t b; + + b.auth_name = hdr_name; + b.hdr_name = auth_name; + b.hdr_value = NULL; + b.pool = pool; + + serf_bucket_headers_do(hdrs, get_auth_header_cb, &b); + + return b.hdr_value; +} + +/* Function is called when 2xx responses are received. Normally we don't + * have to do anything, except for the first response after the + * authentication handshake. This specific response includes authentication + * data which should be validated by the client (mutual authentication). + */ +apr_status_t +serf__validate_response_spnego_auth(const serf__authn_scheme_t *scheme, + peer_t peer, + int code, + serf_connection_t *conn, + serf_request_t *request, + serf_bucket_t *response, + apr_pool_t *pool) +{ + gss_authn_info_t *gss_info; + const char *auth_hdr_name; + + /* TODO: currently this function is only called when a response includes + an Authenticate header. This header is optional. If the server does + not provide this header on the first 2xx response, we will not promote + the connection from undecided to stateful. This won't break anything, + but means we stay in non-pipelining mode. */ + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "Validate Negotiate response header.\n"); + + if (peer == HOST) { + gss_info = conn->authn_baton; + auth_hdr_name = "WWW-Authenticate"; + } else { + gss_info = conn->proxy_authn_baton; + auth_hdr_name = "Proxy-Authenticate"; + } + + if (gss_info->state != gss_api_auth_completed) { + serf_bucket_t *hdrs; + const char *auth_hdr_val; + apr_status_t status; + + hdrs = serf_bucket_response_get_headers(response); + auth_hdr_val = get_auth_header(hdrs, auth_hdr_name, scheme->name, + pool); + + if (auth_hdr_val) { + status = do_auth(peer, code, gss_info, conn, request, auth_hdr_val, + pool); + if (status) { + return status; + } + } else { + /* No Authenticate headers, nothing to validate: authentication + completed.*/ + gss_info->state = gss_api_auth_completed; + + serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt, + "SPNEGO handshake completed.\n"); + } + } + + if (gss_info->state == gss_api_auth_completed) { + switch(gss_info->pstate) { + case pstate_init: + /* Authentication of the first request is done. */ + gss_info->pstate = pstate_undecided; + break; + case pstate_undecided: + /* The server didn't request for authentication even though + we didn't add an Authorization header to previous + request. That means it supports persistent authentication. */ + gss_info->pstate = pstate_stateful; + serf_connection_set_max_outstanding_requests(conn, 0); + break; + default: + /* Nothing to do here. */ + break; + } + } + + return APR_SUCCESS; +} + +#endif /* SERF_HAVE_SPNEGO */ diff -Nru serf-1.1.0/auth/auth_spnego.h serf-1.3.3/auth/auth_spnego.h --- serf-1.1.0/auth/auth_spnego.h 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/auth/auth_spnego.h 2013-06-28 22:40:48.000000000 +0000 @@ -0,0 +1,115 @@ +/* Copyright 2010 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AUTH_SPNEGO_H +#define AUTH_SPNEGO_H + +#include +#include +#include "serf.h" +#include "serf_private.h" + +#if defined(SERF_HAVE_SSPI) +#define SERF_HAVE_SPNEGO +#define SERF_USE_SSPI +#elif defined(SERF_HAVE_GSSAPI) +#define SERF_HAVE_SPNEGO +#define SERF_USE_GSSAPI +#endif + +#ifdef SERF_HAVE_SPNEGO + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct serf__spnego_context_t serf__spnego_context_t; + +typedef struct serf__spnego_buffer_t { + apr_size_t length; + void *value; +} serf__spnego_buffer_t; + +/* Create outbound security context. + * + * All temporary allocations will be performed in SCRATCH_POOL, while security + * context will be allocated in result_pool and will be destroyed automatically + * on RESULT_POOL cleanup. + * + */ +apr_status_t +serf__spnego_create_sec_context(serf__spnego_context_t **ctx_p, + const serf__authn_scheme_t *scheme, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Initialize outbound security context. + * + * The function is used to build a security context between the client + * application and a remote peer. + * + * CTX is pointer to existing context created using + * serf__spnego_create_sec_context() function. + * + * SERVICE is name of Kerberos service name. Usually 'HTTP'. HOSTNAME is + * canonical name of destination server. Caller should resolve server's alias + * to canonical name. + * + * INPUT_BUF is pointer structure describing input token if any. Should be + * zero length on first call. + * + * OUTPUT_BUF will be populated with pointer to output data that should send + * to destination server. This buffer will be automatically freed on + * RESULT_POOL cleanup. + * + * All temporary allocations will be performed in SCRATCH_POOL. + * + * Return value: + * - APR_EAGAIN The client must send the output token to the server and wait + * for a return token. + * + * - APR_SUCCESS The security context was successfully initialized. There is no + * need for another serf__spnego_init_sec_context call. If the function returns + * an output token, that is, if the OUTPUT_BUF is of nonzero length, that + * token must be sent to the server. + * + * Other returns values indicates error. + */ +apr_status_t +serf__spnego_init_sec_context(serf__spnego_context_t *ctx, + const char *service, + const char *hostname, + serf__spnego_buffer_t *input_buf, + serf__spnego_buffer_t *output_buf, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool + ); + +/* + * Reset a previously created security context so we can start with a new one. + * + * This is triggered when the server requires per-request authentication, + * where each request requires a new security context. + */ +apr_status_t +serf__spnego_reset_sec_context(serf__spnego_context_t *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* SERF_HAVE_SPNEGO */ + +#endif /* !AUTH_SPNEGO_H */ diff -Nru serf-1.1.0/auth/auth_spnego_gss.c serf-1.3.3/auth/auth_spnego_gss.c --- serf-1.1.0/auth/auth_spnego_gss.c 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/auth/auth_spnego_gss.c 2013-06-28 22:40:48.000000000 +0000 @@ -0,0 +1,224 @@ +/* Copyright 2009 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "serf.h" +#include "serf_private.h" +#include "auth_spnego.h" + +#ifdef SERF_USE_GSSAPI +#include +#include + + +/* This module can support all authentication mechanisms as provided by + the GSS-API implementation, but for now it only supports SPNEGO for + Negotiate. + SPNEGO can delegate authentication to Kerberos if supported by the + host. */ + +#ifndef GSS_SPNEGO_MECHANISM +static gss_OID_desc spnego_mech_oid = { 6, "\x2b\x06\x01\x05\x05\x02" }; +#define GSS_SPNEGO_MECHANISM &spnego_mech_oid +#endif + +struct serf__spnego_context_t +{ + /* GSSAPI context */ + gss_ctx_id_t gss_ctx; + + /* Mechanism used to authenticate. */ + gss_OID gss_mech; +}; + +static void +log_error(int verbose_flag, const char *filename, + serf__spnego_context_t *ctx, + OM_uint32 err_maj_stat, + OM_uint32 err_min_stat, + const char *msg) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc stat_buff; + OM_uint32 msg_ctx = 0; + + if (verbose_flag) { + maj_stat = gss_display_status(&min_stat, + err_maj_stat, + GSS_C_GSS_CODE, + ctx->gss_mech, + &msg_ctx, + &stat_buff); + if (maj_stat == GSS_S_COMPLETE || + maj_stat == GSS_S_FAILURE) { + maj_stat = gss_display_status(&min_stat, + err_min_stat, + GSS_C_MECH_CODE, + ctx->gss_mech, + &msg_ctx, + &stat_buff); + } + + serf__log(verbose_flag, filename, + "%s (%x,%d): %s\n", msg, + err_maj_stat, err_min_stat, stat_buff.value); + } +} + +/* Cleans the GSS context object, when the pool used to create it gets + cleared or destroyed. */ +static apr_status_t +cleanup_ctx(void *data) +{ + serf__spnego_context_t *ctx = data; + + if (ctx->gss_ctx != GSS_C_NO_CONTEXT) { + OM_uint32 gss_min_stat, gss_maj_stat; + + gss_maj_stat = gss_delete_sec_context(&gss_min_stat, &ctx->gss_ctx, + GSS_C_NO_BUFFER); + if(GSS_ERROR(gss_maj_stat)) { + log_error(AUTH_VERBOSE, __FILE__, ctx, + gss_maj_stat, gss_min_stat, + "Error cleaning up GSS security context"); + return SERF_ERROR_AUTHN_FAILED; + } + } + + return APR_SUCCESS; +} + +static apr_status_t +cleanup_sec_buffer(void *data) +{ + OM_uint32 min_stat; + gss_buffer_desc *gss_buf = data; + + gss_release_buffer(&min_stat, gss_buf); + + return APR_SUCCESS; +} + +apr_status_t +serf__spnego_create_sec_context(serf__spnego_context_t **ctx_p, + const serf__authn_scheme_t *scheme, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + serf__spnego_context_t *ctx; + + ctx = apr_pcalloc(result_pool, sizeof(*ctx)); + + ctx->gss_ctx = GSS_C_NO_CONTEXT; + ctx->gss_mech = GSS_SPNEGO_MECHANISM; + + apr_pool_cleanup_register(result_pool, ctx, + cleanup_ctx, + apr_pool_cleanup_null); + + *ctx_p = ctx; + + return APR_SUCCESS; +} + +apr_status_t +serf__spnego_reset_sec_context(serf__spnego_context_t *ctx) +{ + OM_uint32 dummy_stat; + + if (ctx->gss_ctx) + (void)gss_delete_sec_context(&dummy_stat, &ctx->gss_ctx, + GSS_C_NO_BUFFER); + ctx->gss_ctx = GSS_C_NO_CONTEXT; + + return APR_SUCCESS; +} + +apr_status_t +serf__spnego_init_sec_context(serf__spnego_context_t *ctx, + const char *service, + const char *hostname, + serf__spnego_buffer_t *input_buf, + serf__spnego_buffer_t *output_buf, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool + ) +{ + gss_buffer_desc gss_input_buf = GSS_C_EMPTY_BUFFER; + gss_buffer_desc *gss_output_buf_p; + OM_uint32 gss_min_stat, gss_maj_stat; + gss_name_t host_gss_name; + gss_buffer_desc bufdesc; + gss_OID dummy; /* unused */ + + /* Get the name for the HTTP service at the target host. */ + /* TODO: should be shared between multiple requests. */ + bufdesc.value = apr_pstrcat(scratch_pool, service, "@", hostname, NULL); + bufdesc.length = strlen(bufdesc.value); + serf__log(AUTH_VERBOSE, __FILE__, "Get principal for %s\n", bufdesc.value); + gss_maj_stat = gss_import_name (&gss_min_stat, &bufdesc, + GSS_C_NT_HOSTBASED_SERVICE, + &host_gss_name); + if(GSS_ERROR(gss_maj_stat)) { + log_error(AUTH_VERBOSE, __FILE__, ctx, + gss_maj_stat, gss_min_stat, + "Error converting principal name to GSS internal format "); + return SERF_ERROR_AUTHN_FAILED; + } + + /* If the server sent us a token, pass it to gss_init_sec_token for + validation. */ + gss_input_buf.value = input_buf->value; + gss_input_buf.length = input_buf->length; + + gss_output_buf_p = apr_pcalloc(result_pool, sizeof(*gss_output_buf_p)); + + /* Establish a security context to the server. */ + gss_maj_stat = gss_init_sec_context + (&gss_min_stat, /* minor_status */ + GSS_C_NO_CREDENTIAL, /* XXXXX claimant_cred_handle */ + &ctx->gss_ctx, /* gssapi context handle */ + host_gss_name, /* HTTP@server name */ + ctx->gss_mech, /* mech_type (SPNEGO) */ + GSS_C_MUTUAL_FLAG, /* ensure the peer authenticates itself */ + 0, /* default validity period */ + GSS_C_NO_CHANNEL_BINDINGS, /* do not use channel bindings */ + &gss_input_buf, /* server token, initially empty */ + &dummy, /* actual mech type */ + gss_output_buf_p, /* output_token */ + NULL, /* ret_flags */ + NULL /* not interested in remaining validity */ + ); + + apr_pool_cleanup_register(result_pool, gss_output_buf_p, + cleanup_sec_buffer, + apr_pool_cleanup_null); + + output_buf->value = gss_output_buf_p->value; + output_buf->length = gss_output_buf_p->length; + + switch(gss_maj_stat) { + case GSS_S_COMPLETE: + return APR_SUCCESS; + case GSS_S_CONTINUE_NEEDED: + return APR_EAGAIN; + default: + log_error(AUTH_VERBOSE, __FILE__, ctx, + gss_maj_stat, gss_min_stat, + "Error during Kerberos handshake"); + return SERF_ERROR_AUTHN_FAILED; + } +} + +#endif /* SERF_USE_GSSAPI */ diff -Nru serf-1.1.0/auth/auth_spnego_sspi.c serf-1.3.3/auth/auth_spnego_sspi.c --- serf-1.1.0/auth/auth_spnego_sspi.c 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/auth/auth_spnego_sspi.c 2013-06-28 22:40:48.000000000 +0000 @@ -0,0 +1,297 @@ +/* Copyright 2010 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auth_spnego.h" +#include "serf.h" +#include "serf_private.h" + +#ifdef SERF_USE_SSPI +#include +#include + +#define SECURITY_WIN32 +#include + +/* SEC_E_MUTUAL_AUTH_FAILED is not defined in Windows Platform SDK 5.0. */ +#ifndef SEC_E_MUTUAL_AUTH_FAILED +#define SEC_E_MUTUAL_AUTH_FAILED _HRESULT_TYPEDEF_(0x80090363L) +#endif + +struct serf__spnego_context_t +{ + CredHandle sspi_credentials; + CtxtHandle sspi_context; + BOOL initalized; + apr_pool_t *pool; + + /* Service Principal Name (SPN) used for authentication. */ + const char *target_name; + + /* One of SERF_AUTHN_* authentication types.*/ + int authn_type; +}; + +/* Map SECURITY_STATUS from SSPI to APR error code. Some error codes mapped + * to our own codes and some to Win32 error codes: + * http://support.microsoft.com/kb/113996 + */ +static apr_status_t +map_sspi_status(SECURITY_STATUS sspi_status) +{ + switch(sspi_status) + { + case SEC_E_INSUFFICIENT_MEMORY: + return APR_FROM_OS_ERROR(ERROR_NO_SYSTEM_RESOURCES); + case SEC_E_INVALID_HANDLE: + return APR_FROM_OS_ERROR(ERROR_INVALID_HANDLE); + case SEC_E_UNSUPPORTED_FUNCTION: + return APR_FROM_OS_ERROR(ERROR_INVALID_FUNCTION); + case SEC_E_TARGET_UNKNOWN: + return APR_FROM_OS_ERROR(ERROR_BAD_NETPATH); + case SEC_E_INTERNAL_ERROR: + return APR_FROM_OS_ERROR(ERROR_INTERNAL_ERROR); + case SEC_E_SECPKG_NOT_FOUND: + case SEC_E_BAD_PKGID: + return APR_FROM_OS_ERROR(ERROR_NO_SUCH_PACKAGE); + case SEC_E_NO_IMPERSONATION: + return APR_FROM_OS_ERROR(ERROR_CANNOT_IMPERSONATE); + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + return APR_FROM_OS_ERROR(ERROR_NO_LOGON_SERVERS); + case SEC_E_UNTRUSTED_ROOT: + return APR_FROM_OS_ERROR(ERROR_TRUST_FAILURE); + case SEC_E_WRONG_PRINCIPAL: + return APR_FROM_OS_ERROR(ERROR_WRONG_TARGET_NAME); + case SEC_E_MUTUAL_AUTH_FAILED: + return APR_FROM_OS_ERROR(ERROR_MUTUAL_AUTH_FAILED); + case SEC_E_TIME_SKEW: + return APR_FROM_OS_ERROR(ERROR_TIME_SKEW); + default: + return SERF_ERROR_AUTHN_FAILED; + } +} + +/* Cleans the SSPI context object, when the pool used to create it gets + cleared or destroyed. */ +static apr_status_t +cleanup_ctx(void *data) +{ + serf__spnego_context_t *ctx = data; + + if (SecIsValidHandle(&ctx->sspi_context)) { + DeleteSecurityContext(&ctx->sspi_context); + SecInvalidateHandle(&ctx->sspi_context); + } + + if (SecIsValidHandle(&ctx->sspi_credentials)) { + FreeCredentialsHandle(&ctx->sspi_context); + SecInvalidateHandle(&ctx->sspi_context); + } + + return APR_SUCCESS; +} + +static apr_status_t +cleanup_sec_buffer(void *data) +{ + FreeContextBuffer(data); + + return APR_SUCCESS; +} + +apr_status_t +serf__spnego_create_sec_context(serf__spnego_context_t **ctx_p, + const serf__authn_scheme_t *scheme, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SECURITY_STATUS sspi_status; + serf__spnego_context_t *ctx; + const char *sspi_package; + + ctx = apr_pcalloc(result_pool, sizeof(*ctx)); + + SecInvalidateHandle(&ctx->sspi_context); + SecInvalidateHandle(&ctx->sspi_credentials); + ctx->initalized = FALSE; + ctx->pool = result_pool; + ctx->target_name = NULL; + ctx->authn_type = scheme->type; + + apr_pool_cleanup_register(result_pool, ctx, + cleanup_ctx, + apr_pool_cleanup_null); + + if (ctx->authn_type == SERF_AUTHN_NEGOTIATE) + sspi_package = "Negotiate"; + else + sspi_package = "NTLM"; + + sspi_status = AcquireCredentialsHandle( + NULL, sspi_package, SECPKG_CRED_OUTBOUND, + NULL, NULL, NULL, NULL, + &ctx->sspi_credentials, NULL); + + if (FAILED(sspi_status)) { + return map_sspi_status(sspi_status); + } + + *ctx_p = ctx; + + return APR_SUCCESS; +} + +static apr_status_t +get_canonical_hostname(const char **canonname, + const char *hostname, + apr_pool_t *pool) +{ + struct addrinfo hints; + struct addrinfo *addrinfo; + + ZeroMemory(&hints, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + + if (getaddrinfo(hostname, NULL, &hints, &addrinfo)) { + return apr_get_netos_error(); + } + + if (addrinfo) { + *canonname = apr_pstrdup(pool, addrinfo->ai_canonname); + } + else { + *canonname = apr_pstrdup(pool, hostname); + } + + freeaddrinfo(addrinfo); + return APR_SUCCESS; +} + +apr_status_t +serf__spnego_reset_sec_context(serf__spnego_context_t *ctx) +{ + if (SecIsValidHandle(&ctx->sspi_context)) { + DeleteSecurityContext(&ctx->sspi_context); + SecInvalidateHandle(&ctx->sspi_context); + } + + ctx->initalized = FALSE; + + return APR_SUCCESS; +} + +apr_status_t +serf__spnego_init_sec_context(serf__spnego_context_t *ctx, + const char *service, + const char *hostname, + serf__spnego_buffer_t *input_buf, + serf__spnego_buffer_t *output_buf, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool + ) +{ + SECURITY_STATUS status; + ULONG actual_attr; + SecBuffer sspi_in_buffer; + SecBufferDesc sspi_in_buffer_desc; + SecBuffer sspi_out_buffer; + SecBufferDesc sspi_out_buffer_desc; + apr_status_t apr_status; + const char *canonname; + + if (!ctx->initalized && ctx->authn_type == SERF_AUTHN_NEGOTIATE) { + apr_status = get_canonical_hostname(&canonname, hostname, scratch_pool); + if (apr_status) { + return apr_status; + } + + ctx->target_name = apr_pstrcat(scratch_pool, service, "/", canonname, + NULL); + + serf__log(AUTH_VERBOSE, __FILE__, + "Using SPN '%s' for '%s'\n", ctx->target_name, hostname); + } + else if (ctx->authn_type == SERF_AUTHN_NTLM) + { + /* Target name is not used for NTLM authentication. */ + ctx->target_name = NULL; + } + + /* Prepare input buffer description. */ + sspi_in_buffer.BufferType = SECBUFFER_TOKEN; + sspi_in_buffer.pvBuffer = input_buf->value; + sspi_in_buffer.cbBuffer = input_buf->length; + + sspi_in_buffer_desc.cBuffers = 1; + sspi_in_buffer_desc.pBuffers = &sspi_in_buffer; + sspi_in_buffer_desc.ulVersion = SECBUFFER_VERSION; + + /* Output buffers. Output buffer will be allocated by system. */ + sspi_out_buffer.BufferType = SECBUFFER_TOKEN; + sspi_out_buffer.pvBuffer = NULL; + sspi_out_buffer.cbBuffer = 0; + + sspi_out_buffer_desc.cBuffers = 1; + sspi_out_buffer_desc.pBuffers = &sspi_out_buffer; + sspi_out_buffer_desc.ulVersion = SECBUFFER_VERSION; + + status = InitializeSecurityContext( + &ctx->sspi_credentials, + ctx->initalized ? &ctx->sspi_context : NULL, + ctx->target_name, + ISC_REQ_ALLOCATE_MEMORY + | ISC_REQ_MUTUAL_AUTH + | ISC_REQ_CONFIDENTIALITY, + 0, /* Reserved1 */ + SECURITY_NETWORK_DREP, + &sspi_in_buffer_desc, + 0, /* Reserved2 */ + &ctx->sspi_context, + &sspi_out_buffer_desc, + &actual_attr, + NULL); + + if (sspi_out_buffer.cbBuffer > 0) { + apr_pool_cleanup_register(result_pool, sspi_out_buffer.pvBuffer, + cleanup_sec_buffer, + apr_pool_cleanup_null); + } + + ctx->initalized = TRUE; + + /* Finish authentication if SSPI requires so. */ + if (status == SEC_I_COMPLETE_NEEDED + || status == SEC_I_COMPLETE_AND_CONTINUE) + { + CompleteAuthToken(&ctx->sspi_context, &sspi_out_buffer_desc); + } + + output_buf->value = sspi_out_buffer.pvBuffer; + output_buf->length = sspi_out_buffer.cbBuffer; + + switch(status) { + case SEC_I_COMPLETE_AND_CONTINUE: + case SEC_I_CONTINUE_NEEDED: + return APR_EAGAIN; + + case SEC_I_COMPLETE_NEEDED: + case SEC_E_OK: + return APR_SUCCESS; + + default: + return map_sspi_status(status); + } +} + +#endif /* SERF_USE_SSPI */ diff -Nru serf-1.1.0/buckets/aggregate_buckets.c serf-1.3.3/buckets/aggregate_buckets.c --- serf-1.1.0/buckets/aggregate_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/aggregate_buckets.c 2013-04-02 20:01:34.000000000 +0000 @@ -353,16 +353,104 @@ int acceptable, int *found, const char **data, apr_size_t *len) { - /* Follow pattern from serf_aggregate_read. */ - return APR_ENOTIMPL; + aggregate_context_t *ctx = bucket->data; + apr_status_t status; + + cleanup_aggregate(ctx, bucket->allocator); + + do { + serf_bucket_t *head; + + *len = 0; + + if (!ctx->list) { + if (ctx->hold_open) { + return ctx->hold_open(ctx->hold_open_baton, bucket); + } + else { + return APR_EOF; + } + } + + head = ctx->list->bucket; + + status = serf_bucket_readline(head, acceptable, found, + data, len); + if (SERF_BUCKET_READ_ERROR(status)) + return status; + + if (status == APR_EOF) { + bucket_list_t *next_list; + + /* head bucket is empty, move to to-be-cleaned-up list. */ + next_list = ctx->list->next; + ctx->list->next = ctx->done; + ctx->done = ctx->list; + ctx->list = next_list; + + /* If we have no more in our list, return EOF. */ + if (!ctx->list) { + if (ctx->hold_open) { + return ctx->hold_open(ctx->hold_open_baton, bucket); + } + else { + return APR_EOF; + } + } + + /* we read something, so bail out and let the appl. read again. */ + if (*len) + status = APR_SUCCESS; + } + + /* continue with APR_SUCCESS or APR_EOF and no data read yet. */ + } while (!*len && status != APR_EAGAIN); + + return status; } static apr_status_t serf_aggregate_peek(serf_bucket_t *bucket, const char **data, apr_size_t *len) { - /* Follow pattern from serf_aggregate_read. */ - return APR_ENOTIMPL; + aggregate_context_t *ctx = bucket->data; + serf_bucket_t *head; + apr_status_t status; + + cleanup_aggregate(ctx, bucket->allocator); + + /* Peek the first bucket in the list, if any. */ + if (!ctx->list) { + *len = 0; + if (ctx->hold_open) { + status = ctx->hold_open(ctx->hold_open_baton, bucket); + if (status == APR_EAGAIN) + status = APR_SUCCESS; + return status; + } + else { + return APR_EOF; + } + } + + head = ctx->list->bucket; + + status = serf_bucket_peek(head, data, len); + + if (status == APR_EOF) { + if (ctx->list->next) { + status = APR_SUCCESS; + } else { + if (ctx->hold_open) { + status = ctx->hold_open(ctx->hold_open_baton, bucket); + if (status == APR_EAGAIN) + status = APR_SUCCESS; + return status; + } + } + } + + return status; } static serf_bucket_t * serf_aggregate_read_bucket( diff -Nru serf-1.1.0/buckets/allocator.c serf-1.3.3/buckets/allocator.c --- serf-1.1.0/buckets/allocator.c 2011-07-13 22:52:52.000000000 +0000 +++ serf-1.3.3/buckets/allocator.c 2013-01-15 23:49:27.000000000 +0000 @@ -144,14 +144,14 @@ } #endif - /* ### this implies buckets cannot cross a fork/exec. desirable? - * - * ### hmm. it probably also means that buckets cannot be AROUND - * ### during a fork/exec. the new process will try to clean them - * ### up and figure out there are unfreed blocks... - */ + /* NOTE: On a fork/exec, the child won't bother cleaning up memory. + This is just fine... the memory will go away at exec. + + NOTE: If the child will NOT perform an exec, then the parent or + the child will need to decide who to clean up any + outstanding connection/buckets (as appropriate). */ apr_pool_cleanup_register(pool, allocator, - allocator_cleanup, allocator_cleanup); + allocator_cleanup, apr_pool_cleanup_null); return allocator; } diff -Nru serf-1.1.0/buckets/buckets.c serf-1.3.3/buckets/buckets.c --- serf-1.1.0/buckets/buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/buckets.c 2013-05-20 11:25:39.000000000 +0000 @@ -17,7 +17,7 @@ #include "serf.h" #include "serf_bucket_util.h" - +#include "serf_private.h" serf_bucket_t *serf_bucket_create( const serf_bucket_type_t *type, @@ -155,6 +155,32 @@ return newstr; } +char *serf_bstrcatv(serf_bucket_alloc_t *allocator, struct iovec *vec, + int vecs, apr_size_t *bytes_written) +{ + int i; + apr_size_t new_len = 0; + char *c, *newstr; + + for (i = 0; i < vecs; i++) { + new_len += vec[i].iov_len; + } + + /* It's up to the caller to free this memory later. */ + newstr = serf_bucket_mem_alloc(allocator, new_len); + + c = newstr; + for (i = 0; i < vecs; i++) { + memcpy(c, vec[i].iov_base, vec[i].iov_len); + c += vec[i].iov_len; + } + + if (bytes_written) { + *bytes_written = c - newstr; + } + + return newstr; +} /* ==================================================================== */ @@ -464,11 +490,10 @@ /* Whatever was read, the line is now ready for use. */ linebuf->state = SERF_LINEBUF_READY; + } else { + /* no data available, try again later. */ + return APR_EAGAIN; } - /* ### we need data. gotta check this char. bail if zero?! */ - /* else len == 0 */ - - /* ### status */ } else { int found; @@ -536,3 +561,80 @@ } /* NOTREACHED */ } + +/* Logging functions. + Use with one of the [COMP]_VERBOSE defines so that the compiler knows to + optimize this code out when no logging is needed. */ +static void log_time() +{ + apr_time_exp_t tm; + + apr_time_exp_lt(&tm, apr_time_now()); + fprintf(stderr, "[%d-%02d-%02dT%02d:%02d:%02d.%06d%+03d] ", + 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, + tm.tm_gmtoff/3600); +} + +void serf__log(int verbose_flag, const char *filename, const char *fmt, ...) +{ + va_list argp; + + if (verbose_flag) { + log_time(); + + if (filename) + fprintf(stderr, "%s: ", filename); + + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + } +} + +void serf__log_nopref(int verbose_flag, const char *fmt, ...) +{ + va_list argp; + + if (verbose_flag) { + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + } +} + +void serf__log_skt(int verbose_flag, const char *filename, apr_socket_t *skt, + const char *fmt, ...) +{ + va_list argp; + + if (verbose_flag) { + apr_sockaddr_t *sa; + log_time(); + + if (skt) { + /* Log local and remote ip address:port */ + fprintf(stderr, "[l:"); + if (apr_socket_addr_get(&sa, APR_LOCAL, skt) == APR_SUCCESS) { + char buf[32]; + apr_sockaddr_ip_getbuf(buf, 32, sa); + fprintf(stderr, "%s:%d", buf, sa->port); + } + fprintf(stderr, " r:"); + if (apr_socket_addr_get(&sa, APR_REMOTE, skt) == APR_SUCCESS) { + char buf[32]; + apr_sockaddr_ip_getbuf(buf, 32, sa); + fprintf(stderr, "%s:%d", buf, sa->port); + } + fprintf(stderr, "] "); + } + + if (filename) + fprintf(stderr, "%s: ", filename); + + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + } +} + diff -Nru serf-1.1.0/buckets/dechunk_buckets.c serf-1.3.3/buckets/dechunk_buckets.c --- serf-1.1.0/buckets/dechunk_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/dechunk_buckets.c 2013-07-15 09:22:40.000000000 +0000 @@ -135,6 +135,11 @@ ctx->body_left = 2; /* CRLF */ } + /* We need more data but there is no more available. */ + if (ctx->body_left && APR_STATUS_IS_EOF(status)) { + return SERF_ERROR_TRUNCATED_HTTP_RESPONSE; + } + /* Return the data we just read. */ return status; @@ -148,10 +153,18 @@ * if we're done reading the chunk terminator. */ ctx->body_left -= *len; + + /* We need more data but there is no more available. */ + if (ctx->body_left && APR_STATUS_IS_EOF(status)) + return SERF_ERROR_TRUNCATED_HTTP_RESPONSE; + if (!ctx->body_left) { ctx->state = STATE_SIZE; } + /* Don't return the CR of CRLF to the caller! */ + *len = 0; + if (status) return status; @@ -159,6 +172,7 @@ case STATE_DONE: /* Just keep returning EOF */ + *len = 0; return APR_EOF; default: diff -Nru serf-1.1.0/buckets/headers_buckets.c serf-1.3.3/buckets/headers_buckets.c --- serf-1.1.0/buckets/headers_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/headers_buckets.c 2013-07-21 14:27:03.000000000 +0000 @@ -163,11 +163,11 @@ be comma-separated, that is clearly the correct behavior; for others, the correct behavior is undefined anyway. */ - /* The "+1" is for the comma; serf_bstrmemdup() will also add - one slot for the terminating '\0'. */ + /* The "+1" is for the comma; the +1 in the alloc + call is for the terminating '\0' */ apr_size_t new_size = found->value_size + value_size + 1; char *new_val = serf_bucket_mem_alloc(headers_bucket->allocator, - new_size); + new_size + 1); memcpy(new_val, val, value_size); new_val[value_size] = ','; memcpy(new_val + value_size + 1, found->value, @@ -325,8 +325,10 @@ apr_size_t avail; select_value(ctx, data, &avail); - if (ctx->state == READ_DONE) + if (ctx->state == READ_DONE) { + *len = avail; return APR_EOF; + } if (requested >= avail) { /* return everything from this chunk */ diff -Nru serf-1.1.0/buckets/limit_buckets.c serf-1.3.3/buckets/limit_buckets.c --- serf-1.1.0/buckets/limit_buckets.c 2011-07-13 02:39:16.000000000 +0000 +++ serf-1.3.3/buckets/limit_buckets.c 2013-05-31 14:20:13.000000000 +0000 @@ -17,14 +17,7 @@ #include "serf.h" #include "serf_bucket_util.h" - -/* Older versions of APR do not have this macro. */ -#ifdef APR_SIZE_MAX -#define REQUESTED_MAX APR_SIZE_MAX -#else -#define REQUESTED_MAX (~((apr_size_t)0)) -#endif - +#include "serf_private.h" typedef struct { serf_bucket_t *stream; diff -Nru serf-1.1.0/buckets/mmap_buckets.c serf-1.3.3/buckets/mmap_buckets.c --- serf-1.1.0/buckets/mmap_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/mmap_buckets.c 2013-05-28 09:07:39.000000000 +0000 @@ -19,6 +19,7 @@ #include "serf.h" #include "serf_bucket_util.h" +#if APR_HAS_MMAP typedef struct { apr_mmap_t *mmap; @@ -116,3 +117,24 @@ serf_mmap_peek, serf_default_destroy_and_data, }; + +#else /* !APR_HAS_MMAP */ + +serf_bucket_t *serf_bucket_mmap_create(apr_mmap_t *file_mmap, + serf_bucket_alloc_t *allocator) +{ + return NULL; +} + +const serf_bucket_type_t serf_bucket_type_mmap = { + "MMAP", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +#endif diff -Nru serf-1.1.0/buckets/request_buckets.c serf-1.3.3/buckets/request_buckets.c --- serf-1.1.0/buckets/request_buckets.c 2012-03-19 21:31:55.000000000 +0000 +++ serf-1.3.3/buckets/request_buckets.c 2013-02-25 07:13:11.000000000 +0000 @@ -105,14 +105,9 @@ iov[3].iov_base = " HTTP/1.1\r\n"; iov[3].iov_len = sizeof(" HTTP/1.1\r\n") - 1; - /* ### pool allocation! */ - new_data = apr_pstrcatv(serf_bucket_allocator_get_pool(bucket->allocator), - iov, 4, &nbytes); - - /* Create a new bucket for this string. A free function isn't needed - * since the string is residing in a pool. - */ - new_bucket = SERF_BUCKET_SIMPLE_STRING_LEN(new_data, nbytes, + /* Create a new bucket for this string with a flat string. */ + new_data = serf_bstrcatv(bucket->allocator, iov, 4, &nbytes); + new_bucket = serf_bucket_simple_own_create(new_data, nbytes, bucket->allocator); /* Build up the new bucket structure. diff -Nru serf-1.1.0/buckets/response_body_buckets.c serf-1.3.3/buckets/response_body_buckets.c --- serf-1.1.0/buckets/response_body_buckets.c 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/buckets/response_body_buckets.c 2012-11-09 12:03:15.000000000 +0000 @@ -0,0 +1,135 @@ +/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "serf.h" +#include "serf_bucket_util.h" + +/* Older versions of APR do not have this macro. */ +#ifdef APR_SIZE_MAX +#define REQUESTED_MAX APR_SIZE_MAX +#else +#define REQUESTED_MAX (~((apr_size_t)0)) +#endif + + +typedef struct { + serf_bucket_t *stream; + apr_uint64_t remaining; +} body_context_t; + +serf_bucket_t *serf_bucket_response_body_create( + serf_bucket_t *stream, apr_uint64_t len, serf_bucket_alloc_t *allocator) +{ + body_context_t *ctx; + + ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); + ctx->stream = stream; + ctx->remaining = len; + + return serf_bucket_create(&serf_bucket_type_response_body, allocator, ctx); +} + +static apr_status_t serf_response_body_read(serf_bucket_t *bucket, + apr_size_t requested, + const char **data, + apr_size_t *len) +{ + body_context_t *ctx = bucket->data; + apr_status_t status; + + if (!ctx->remaining) { + *len = 0; + return APR_EOF; + } + + if (requested == SERF_READ_ALL_AVAIL || requested > ctx->remaining) { + if (ctx->remaining <= REQUESTED_MAX) { + requested = (apr_size_t) ctx->remaining; + } else { + requested = REQUESTED_MAX; + } + } + + status = serf_bucket_read(ctx->stream, requested, data, len); + + if (!SERF_BUCKET_READ_ERROR(status)) { + ctx->remaining -= *len; + } + + if (APR_STATUS_IS_EOF(status) && ctx->remaining > 0) { + /* The server sent less data than expected. */ + status = SERF_ERROR_TRUNCATED_HTTP_RESPONSE; + } + + return status; +} + +static apr_status_t serf_response_body_readline(serf_bucket_t *bucket, + int acceptable, int *found, + const char **data, + apr_size_t *len) +{ + body_context_t *ctx = bucket->data; + apr_status_t status; + + if (!ctx->remaining) { + *len = 0; + return APR_EOF; + } + + status = serf_bucket_readline(ctx->stream, acceptable, found, data, len); + + if (!SERF_BUCKET_READ_ERROR(status)) { + ctx->remaining -= *len; + } + + if (APR_STATUS_IS_EOF(status) && ctx->remaining > 0) { + /* The server sent less data than expected. */ + status = SERF_ERROR_TRUNCATED_HTTP_RESPONSE; + } + + return status; +} + +static apr_status_t serf_response_body_peek(serf_bucket_t *bucket, + const char **data, + apr_size_t *len) +{ + body_context_t *ctx = bucket->data; + + return serf_bucket_peek(ctx->stream, data, len); +} + +static void serf_response_body_destroy(serf_bucket_t *bucket) +{ + body_context_t *ctx = bucket->data; + + serf_bucket_destroy(ctx->stream); + + serf_default_destroy_and_data(bucket); +} + +const serf_bucket_type_t serf_bucket_type_response_body = { + "RESPONSE_BODY", + serf_response_body_read, + serf_response_body_readline, + serf_default_read_iovec, + serf_default_read_for_sendfile, + serf_default_read_bucket, + serf_response_body_peek, + serf_response_body_destroy, +}; diff -Nru serf-1.1.0/buckets/response_buckets.c serf-1.3.3/buckets/response_buckets.c --- serf-1.1.0/buckets/response_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/response_buckets.c 2013-09-29 06:37:46.000000000 +0000 @@ -19,7 +19,7 @@ #include "serf.h" #include "serf_bucket_util.h" - +#include "serf_private.h" typedef struct { serf_bucket_t *stream; @@ -43,6 +43,29 @@ int head_req; /* Was this a HEAD request? */ } response_context_t; +/* Returns 1 if according to RFC2626 this response can have a body, 0 if it + must not have a body. */ +static int expect_body(response_context_t *ctx) +{ + if (ctx->head_req) + return 0; + + /* 100 Continue and 101 Switching Protocols */ + if (ctx->sl.code >= 100 && ctx->sl.code < 200) + return 0; + + /* 204 No Content */ + if (ctx->sl.code == 204) + return 0; + + /* 205? */ + + /* 304 Not Modified */ + if (ctx->sl.code == 304) + return 0; + + return 1; +} serf_bucket_t *serf_bucket_response_create( serf_bucket_t *stream, @@ -238,6 +261,15 @@ /* Advance the state. */ ctx->state = STATE_BODY; + /* If this is a response to a HEAD request, or code == 1xx,204 or304 + then we don't receive a real body. */ + if (!expect_body(ctx)) { + ctx->body = serf_bucket_simple_create(NULL, 0, NULL, NULL, + bkt->allocator); + ctx->state = STATE_BODY; + break; + } + ctx->body = serf_bucket_barrier_create(ctx->stream, bkt->allocator); @@ -249,8 +281,8 @@ if (errno == ERANGE) { return APR_FROM_OS_ERROR(ERANGE); } - ctx->body = serf_bucket_limit_create(ctx->body, length, - bkt->allocator); + ctx->body = serf_bucket_response_body_create( + ctx->body, length, bkt->allocator); } else { v = serf_bucket_headers_get(ctx->headers, "Transfer-Encoding"); @@ -261,10 +293,6 @@ ctx->body = serf_bucket_dechunk_create(ctx->body, bkt->allocator); } - - if (!v && (ctx->sl.code == 204 || ctx->sl.code == 304)) { - ctx->state = STATE_DONE; - } } v = serf_bucket_headers_get(ctx->headers, "Content-Encoding"); if (v) { @@ -280,10 +308,6 @@ SERF_DEFLATE_DEFLATE); } } - /* If we're a HEAD request, we don't receive a body. */ - if (ctx->head_req) { - ctx->state = STATE_DONE; - } } break; case STATE_BODY: @@ -385,13 +409,15 @@ } rv = serf_bucket_read(ctx->body, requested, data, len); + if (SERF_BUCKET_READ_ERROR(rv)) + return rv; + if (APR_STATUS_IS_EOF(rv)) { if (ctx->chunked) { ctx->state = STATE_TRAILERS; /* Mask the result. */ rv = APR_SUCCESS; - } - else { + } else { ctx->state = STATE_DONE; } } @@ -414,6 +440,39 @@ return serf_bucket_readline(ctx->body, acceptable, found, data, len); } +apr_status_t serf_response_full_become_aggregate(serf_bucket_t *bucket) +{ + response_context_t *ctx = bucket->data; + serf_bucket_t *bkt; + char buf[256]; + int size; + + serf_bucket_aggregate_become(bucket); + + /* Add reconstructed status line. */ + size = apr_snprintf(buf, 256, "HTTP/%d.%d %d ", + SERF_HTTP_VERSION_MAJOR(ctx->sl.version), + SERF_HTTP_VERSION_MINOR(ctx->sl.version), + ctx->sl.code); + bkt = serf_bucket_simple_copy_create(buf, size, + bucket->allocator); + serf_bucket_aggregate_append(bucket, bkt); + bkt = serf_bucket_simple_copy_create(ctx->sl.reason, strlen(ctx->sl.reason), + bucket->allocator); + serf_bucket_aggregate_append(bucket, bkt); + bkt = SERF_BUCKET_SIMPLE_STRING_LEN("\r\n", 2, + bucket->allocator); + serf_bucket_aggregate_append(bucket, bkt); + + /* Add headers and stream buckets in order. */ + serf_bucket_aggregate_append(bucket, ctx->headers); + serf_bucket_aggregate_append(bucket, ctx->stream); + + serf_bucket_mem_free(bucket->allocator, ctx); + + return APR_SUCCESS; +} + /* ### need to implement */ #define serf_response_peek NULL diff -Nru serf-1.1.0/buckets/simple_buckets.c serf-1.3.3/buckets/simple_buckets.c --- serf-1.1.0/buckets/simple_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/simple_buckets.c 2013-02-25 07:13:11.000000000 +0000 @@ -71,6 +71,23 @@ return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx); } +serf_bucket_t *serf_bucket_simple_own_create( + const char *data, apr_size_t len, + serf_bucket_alloc_t *allocator) +{ + simple_context_t *ctx; + + ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); + + ctx->original = ctx->current = data; + + ctx->remaining = len; + ctx->freefunc = free_copied_data; + ctx->baton = allocator; + + return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx); +} + static apr_status_t serf_simple_read(serf_bucket_t *bucket, apr_size_t requested, const char **data, apr_size_t *len) diff -Nru serf-1.1.0/buckets/socket_buckets.c serf-1.3.3/buckets/socket_buckets.c --- serf-1.1.0/buckets/socket_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/buckets/socket_buckets.c 2013-09-29 06:37:46.000000000 +0000 @@ -17,6 +17,7 @@ #include #include "serf.h" +#include "serf_private.h" #include "serf_bucket_util.h" @@ -40,7 +41,16 @@ *len = bufsize; status = apr_socket_recv(ctx->skt, buf, len); - if (ctx->progress_func) + if (status && !APR_STATUS_IS_EAGAIN(status)) + serf__log_skt(SOCK_VERBOSE, __FILE__, ctx->skt, + "socket_recv error %d\n", status); + + if (*len) + serf__log_skt(SOCK_MSG_VERBOSE, __FILE__, ctx->skt, + "--- socket_recv:\n%.*s\n-(%d)-\n", + *len, buf, *len); + + if (ctx->progress_func && *len) ctx->progress_func(ctx->progress_baton, *len, 0); return status; @@ -60,7 +70,8 @@ ctx->databuf.read = socket_reader; ctx->databuf.read_baton = ctx; - ctx->progress_func = ctx->progress_baton = NULL; + ctx->progress_func = NULL; + ctx->progress_baton = NULL; return serf_bucket_create(&serf_bucket_type_socket, allocator, ctx); } diff -Nru serf-1.1.0/buckets/ssl_buckets.c serf-1.3.3/buckets/ssl_buckets.c --- serf-1.1.0/buckets/ssl_buckets.c 2012-04-19 21:43:22.000000000 +0000 +++ serf-1.3.3/buckets/ssl_buckets.c 2013-11-29 21:22:42.000000000 +0000 @@ -43,6 +43,7 @@ #include #include "serf.h" +#include "serf_private.h" #include "serf_bucket_util.h" #include @@ -64,8 +65,6 @@ #endif -/*#define SSL_VERBOSE*/ - /* * Here's an overview of the SSL bucket's relationship to OpenSSL and serf. * @@ -180,6 +179,10 @@ EVP_PKEY *cached_cert_pw; apr_status_t pending_err; + + /* Status of a fatal error, returned on subsequent encrypt or decrypt + requests. */ + apr_status_t fatal_err; }; typedef struct { @@ -198,6 +201,47 @@ int depth; }; +static void disable_compression(serf_ssl_context_t *ssl_ctx); + +#if SSL_VERBOSE +/* Log all ssl alerts that we receive from the server. */ +static void +apps_ssl_info_callback(const SSL *s, int where, int ret) +{ + const char *str; + int w; + w = where & ~SSL_ST_MASK; + + if (w & SSL_ST_CONNECT) + str = "SSL_connect"; + else if (w & SSL_ST_ACCEPT) + str = "SSL_accept"; + else + str = "undefined"; + + if (where & SSL_CB_LOOP) { + serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str, + SSL_state_string_long(s)); + } + else if (where & SSL_CB_ALERT) { + str = (where & SSL_CB_READ) ? "read" : "write"; + serf__log(SSL_VERBOSE, __FILE__, "SSL3 alert %s:%s:%s\n", + str, + SSL_alert_type_string_long(ret), + SSL_alert_desc_string_long(ret)); + } + else if (where & SSL_CB_EXIT) { + if (ret == 0) + serf__log(SSL_VERBOSE, __FILE__, "%s:failed in %s\n", str, + SSL_state_string_long(s)); + else if (ret < 0) { + serf__log(SSL_VERBOSE, __FILE__, "%s:error in %s\n", str, + SSL_state_string_long(s)); + } + } +} +#endif + /* Returns the amount read. */ static int bio_bucket_read(BIO *bio, char *in, int inlen) { @@ -206,17 +250,15 @@ apr_status_t status; apr_size_t len; -#ifdef SSL_VERBOSE - printf("bio_bucket_read called for %d bytes\n", inlen); -#endif + serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read called for %d bytes\n", + inlen); if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN && BIO_should_read(ctx->bio)) { -#ifdef SSL_VERBOSE - printf("bio_bucket_read waiting: (%d %d %d)\n", + serf__log(SSL_VERBOSE, __FILE__, + "bio_bucket_read waiting: (%d %d %d)\n", BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), BIO_get_retry_flags(ctx->bio)); -#endif /* Falling back... */ ctx->encrypt.exhausted_reset = 1; BIO_clear_retry_flags(bio); @@ -225,9 +267,9 @@ status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len); ctx->decrypt.status = status; -#ifdef SSL_VERBOSE - printf("bio_bucket_read received %d bytes (%d)\n", len, status); -#endif + + serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read received %d bytes (%d)\n", + len, status); if (!SERF_BUCKET_READ_ERROR(status)) { /* Oh suck. */ @@ -250,16 +292,15 @@ serf_ssl_context_t *ctx = bio->ptr; serf_bucket_t *tmp; -#ifdef SSL_VERBOSE - printf("bio_bucket_write called for %d bytes\n", inl); -#endif + serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write called for %d bytes\n", + inl); + if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN && !BIO_should_read(ctx->bio)) { -#ifdef SSL_VERBOSE - printf("bio_bucket_write waiting: (%d %d %d)\n", + serf__log(SSL_VERBOSE, __FILE__, + "bio_bucket_write waiting: (%d %d %d)\n", BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), BIO_get_retry_flags(ctx->bio)); -#endif /* Falling back... */ ctx->encrypt.exhausted_reset = 1; BIO_clear_retry_flags(bio); @@ -422,8 +463,12 @@ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_INVALID_CA: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: failures |= SERF_SSL_CERT_UNKNOWNCA; break; + case X509_V_ERR_CERT_REVOKED: + failures |= SERF_SSL_CERT_REVOKED; + break; default: failures |= SERF_SSL_CERT_UNKNOWN_FAILURE; break; @@ -455,9 +500,13 @@ failures, cert); if (status == APR_SUCCESS) cert_valid = 1; - else + else { + /* Even if openssl found the certificate valid, the application + told us to reject it. */ + cert_valid = 0; /* Pass the error back to the caller through the context-run. */ ctx->pending_err = status; + } apr_pool_destroy(subpool); } @@ -490,7 +539,7 @@ certs_len = 1; } else { int i; - + certs_len = sk_X509_num(chain); /* Room for all the certs and a trailing NULL. */ @@ -514,6 +563,9 @@ if (status == APR_SUCCESS) { cert_valid = 1; } else { + /* Even if openssl found the certificate valid, the application + told us to reject it. */ + cert_valid = 0; /* Pass the error back to the caller through the context-run. */ ctx->pending_err = status; } @@ -521,6 +573,15 @@ apr_pool_destroy(subpool); } + /* Return a specific error if the server certificate is not accepted by + OpenSSL and the application has not set callbacks to override this. */ + if (!cert_valid && + !ctx->server_cert_chain_callback && + !ctx->server_cert_callback) + { + ctx->pending_err = SERF_ERROR_SSL_CERT_FAILED; + } + return cert_valid; } @@ -534,18 +595,18 @@ const char *data; int ssl_len; -#ifdef SSL_VERBOSE - printf("ssl_decrypt: begin %d\n", bufsize); -#endif + if (ctx->fatal_err) + return ctx->fatal_err; + + serf__log(SSL_VERBOSE, __FILE__, "ssl_decrypt: begin %d\n", bufsize); /* Is there some data waiting to be read? */ ssl_len = SSL_read(ctx->ssl, buf, bufsize); if (ssl_len > 0) { -#ifdef SSL_VERBOSE - printf("ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n", - ssl_len, bufsize, ctx->decrypt.status, - BIO_get_retry_flags(ctx->bio)); -#endif + serf__log(SSL_VERBOSE, __FILE__, + "ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n", + ssl_len, bufsize, ctx->decrypt.status, + BIO_get_retry_flags(ctx->bio)); *len = ssl_len; return APR_SUCCESS; } @@ -555,10 +616,9 @@ if (!SERF_BUCKET_READ_ERROR(status) && priv_len) { serf_bucket_t *tmp; -#ifdef SSL_VERBOSE - printf("ssl_decrypt: read %d bytes (%d); status: %d\n", priv_len, - bufsize, status); -#endif + serf__log(SSL_VERBOSE, __FILE__, + "ssl_decrypt: read %d bytes (%d); status: %d\n", + priv_len, bufsize, status); tmp = serf_bucket_simple_copy_create(data, priv_len, ctx->decrypt.pending->allocator); @@ -573,37 +633,66 @@ switch (ssl_err) { case SSL_ERROR_SYSCALL: *len = 0; + /* Return the underlying network error that caused OpenSSL + to fail. ### This can be a crypt error! */ status = ctx->decrypt.status; break; case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: *len = 0; status = APR_EAGAIN; break; case SSL_ERROR_SSL: *len = 0; - status = ctx->pending_err ? ctx->pending_err : APR_EGENERAL; - ctx->pending_err = 0; + if (ctx->pending_err) { + status = ctx->pending_err; + ctx->pending_err = 0; + } else { + ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; + } break; default: *len = 0; - status = APR_EGENERAL; + ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; break; } - } - else { + } else if (ssl_len == 0) { + /* The server shut down the connection. */ + int ssl_err, shutdown; + *len = 0; + + /* Check for SSL_RECEIVED_SHUTDOWN */ + shutdown = SSL_get_shutdown(ctx->ssl); + /* Check for SSL_ERROR_ZERO_RETURN */ + ssl_err = SSL_get_error(ctx->ssl, ssl_len); + + if (shutdown == SSL_RECEIVED_SHUTDOWN && + ssl_err == SSL_ERROR_ZERO_RETURN) { + /* The server closed the SSL session. While this doesn't + necessary mean the connection is closed, let's close + it here anyway. + We can optimize this later. */ + serf__log(SSL_VERBOSE, __FILE__, + "ssl_decrypt: SSL read error: server" + " shut down connection!\n"); + status = APR_EOF; + } else { + /* A fatal error occurred. */ + ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED; + } + } else { *len = ssl_len; -#ifdef SSL_VERBOSE - printf("---\n%s\n-(%d)-\n", buf, *len); -#endif + serf__log(SSL_MSG_VERBOSE, __FILE__, + "---\n%.*s\n-(%d)-\n", *len, buf, *len); } } else { *len = 0; } -#ifdef SSL_VERBOSE - printf("ssl_decrypt: %d %d %d\n", status, *len, - BIO_get_retry_flags(ctx->bio)); -#endif + serf__log(SSL_VERBOSE, __FILE__, + "ssl_decrypt: %d %d %d\n", status, *len, + BIO_get_retry_flags(ctx->bio)); + return status; } @@ -616,9 +705,10 @@ serf_ssl_context_t *ctx = baton; apr_status_t status; -#ifdef SSL_VERBOSE - printf("ssl_encrypt: begin %d\n", bufsize); -#endif + if (ctx->fatal_err) + return ctx->fatal_err; + + serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: begin %d\n", bufsize); /* Try to read already encrypted but unread data first. */ status = serf_bucket_read(ctx->encrypt.pending, bufsize, &data, len); @@ -632,29 +722,28 @@ if (APR_STATUS_IS_EOF(status)) { status = APR_SUCCESS; } -#ifdef SSL_VERBOSE - printf("ssl_encrypt: %d %d %d (quick read)\n", status, *len, - BIO_get_retry_flags(ctx->bio)); -#endif + + serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: %d %d %d (quick read)\n", + status, *len, BIO_get_retry_flags(ctx->bio)); + return status; } if (BIO_should_retry(ctx->bio) && BIO_should_write(ctx->bio)) { -#ifdef SSL_VERBOSE - printf("ssl_encrypt: %d %d %d (should write exit)\n", status, *len, - BIO_get_retry_flags(ctx->bio)); -#endif + serf__log(SSL_VERBOSE, __FILE__, + "ssl_encrypt: %d %d %d (should write exit)\n", + status, *len, BIO_get_retry_flags(ctx->bio)); + return APR_EAGAIN; } /* If we were previously blocked, unblock ourselves now. */ if (BIO_should_read(ctx->bio)) { -#ifdef SSL_VERBOSE - printf("ssl_encrypt: reset %d %d (%d %d %d)\n", status, - ctx->encrypt.status, - BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), - BIO_get_retry_flags(ctx->bio)); -#endif + serf__log(SSL_VERBOSE, __FILE__, "ssl_encrypt: reset %d %d (%d %d %d)\n", + status, ctx->encrypt.status, + BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), + BIO_get_retry_flags(ctx->bio)); + ctx->encrypt.status = APR_SUCCESS; ctx->encrypt.exhausted_reset = 0; } @@ -696,34 +785,42 @@ interim_bufsize -= vecs_data_len; interim_len = vecs_data_len; -#ifdef SSL_VERBOSE - printf("ssl_encrypt: bucket read %d bytes; status %d\n", - interim_len, status); - printf("---\n%s\n-(%d)-\n", vecs_data, interim_len); -#endif + serf__log(SSL_VERBOSE, __FILE__, + "ssl_encrypt: bucket read %d bytes; "\ + "status %d\n", interim_len, status); + serf__log(SSL_MSG_VERBOSE, __FILE__, "---\n%.*s\n-(%d)-\n", + interim_len, vecs_data, interim_len); + /* Stash our status away. */ ctx->encrypt.status = status; ssl_len = SSL_write(ctx->ssl, vecs_data, interim_len); -#ifdef SSL_VERBOSE - printf("ssl_encrypt: SSL write: %d\n", ssl_len); -#endif - /* We're done. */ - serf_bucket_mem_free(ctx->allocator, vecs_data); + + serf__log(SSL_VERBOSE, __FILE__, + "ssl_encrypt: SSL write: %d\n", ssl_len); /* If we failed to write... */ if (ssl_len < 0) { int ssl_err; - /* Ah, bugger. We need to put that data back. */ - serf_bucket_aggregate_prepend_iovec(ctx->encrypt.stream, - vecs, vecs_read); + /* Ah, bugger. We need to put that data back. + Note: use the copy here, we do not own the original iovec + data buffer so it will be freed on next read. */ + serf_bucket_t *vecs_copy = + serf_bucket_simple_own_create(vecs_data, + vecs_data_len, + ctx->allocator); + serf_bucket_aggregate_prepend(ctx->encrypt.stream, + vecs_copy); ssl_err = SSL_get_error(ctx->ssl, ssl_len); -#ifdef SSL_VERBOSE - printf("ssl_encrypt: SSL write error: %d\n", ssl_err); -#endif + + serf__log(SSL_VERBOSE, __FILE__, + "ssl_encrypt: SSL write error: %d\n", ssl_err); + if (ssl_err == SSL_ERROR_SYSCALL) { + /* Return the underlying network error that caused OpenSSL + to fail. ### This can be a decrypt error! */ status = ctx->encrypt.status; if (SERF_BUCKET_READ_ERROR(status)) { return status; @@ -735,12 +832,17 @@ status = SERF_ERROR_WAIT_CONN; } else { - status = APR_EGENERAL; + ctx->fatal_err = status = + SERF_ERROR_SSL_COMM_FAILED; } } -#ifdef SSL_VERBOSE - printf("ssl_encrypt: SSL write error: %d %d\n", status, *len); -#endif + + serf__log(SSL_VERBOSE, __FILE__, + "ssl_encrypt: SSL write error: %d %d\n", + status, *len); + } else { + /* We're done with this data. */ + serf_bucket_mem_free(ctx->allocator, vecs_data); } } } @@ -767,10 +869,9 @@ *len += vecs[i].iov_len; } -#ifdef SSL_VERBOSE - printf("ssl_encrypt read agg: %d %d %d %d\n", status, agg_status, - ctx->encrypt.status, *len); -#endif + serf__log(SSL_VERBOSE, __FILE__, + "ssl_encrypt read agg: %d %d %d %d\n", status, agg_status, + ctx->encrypt.status, *len); if (!agg_status) { status = agg_status; @@ -783,11 +884,11 @@ ctx->encrypt.status = SERF_ERROR_WAIT_CONN; } -#ifdef SSL_VERBOSE - printf("ssl_encrypt finished: %d %d (%d %d %d)\n", status, *len, - BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), - BIO_get_retry_flags(ctx->bio)); -#endif + serf__log(SSL_VERBOSE, __FILE__, + "ssl_encrypt finished: %d %d (%d %d %d)\n", status, *len, + BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), + BIO_get_retry_flags(ctx->bio)); + return status; } @@ -873,6 +974,20 @@ #if APR_HAS_THREADS int i, numlocks; #endif + +#ifdef SSL_VERBOSE + /* Warn when compile-time and run-time version of OpenSSL differ in + major/minor version number. */ + long libver = SSLeay(); + + if ((libver ^ OPENSSL_VERSION_NUMBER) & 0xFFF00000) { + serf__log(SSL_VERBOSE, __FILE__, + "Warning: OpenSSL library version mismatch, compile-time " + "was %lx, runtime is %lx.\n", + OPENSSL_VERSION_NUMBER, libver); + } +#endif + CRYPTO_malloc_init(); ERR_load_crypto_strings(); SSL_load_error_strings(); @@ -933,7 +1048,7 @@ } if (status || !cert_path) { - break; + break; } /* Load the x.509 cert file stored in PKCS12 */ @@ -1084,21 +1199,16 @@ context->server_cert_userdata = data; } -static serf_ssl_context_t *ssl_init_context(void) +static serf_ssl_context_t *ssl_init_context(serf_bucket_alloc_t *allocator) { serf_ssl_context_t *ssl_ctx; - apr_pool_t *pool; - serf_bucket_alloc_t *allocator; init_ssl_libraries(); - apr_pool_create(&pool, NULL); - allocator = serf_bucket_allocator_create(pool, NULL, NULL); - ssl_ctx = serf_bucket_mem_alloc(allocator, sizeof(*ssl_ctx)); ssl_ctx->refcount = 0; - ssl_ctx->pool = pool; + ssl_ctx->pool = serf_bucket_allocator_get_pool(allocator); ssl_ctx->allocator = allocator; ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method()); @@ -1107,6 +1217,7 @@ ssl_ctx->cached_cert = 0; ssl_ctx->cached_cert_pw = 0; ssl_ctx->pending_err = APR_SUCCESS; + ssl_ctx->fatal_err = APR_SUCCESS; ssl_ctx->cert_callback = NULL; ssl_ctx->cert_pw_callback = NULL; @@ -1116,6 +1227,8 @@ SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER, validate_server_certificate); SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL); + /* Disable SSL compression by default. */ + disable_compression(ssl_ctx); ssl_ctx->ssl = SSL_new(ssl_ctx->ctx); ssl_ctx->bio = BIO_new(&bio_bucket_method); @@ -1127,6 +1240,10 @@ SSL_set_app_data(ssl_ctx->ssl, ssl_ctx); +#if SSL_VERBOSE + SSL_CTX_set_info_callback(ssl_ctx->ctx, apps_ssl_info_callback); +#endif + ssl_ctx->encrypt.stream = NULL; ssl_ctx->encrypt.stream_next = NULL; ssl_ctx->encrypt.pending = serf_bucket_aggregate_create(allocator); @@ -1148,8 +1265,6 @@ static apr_status_t ssl_free_context( serf_ssl_context_t *ssl_ctx) { - apr_pool_t *p; - /* If never had the pending buckets, don't try to free them. */ if (ssl_ctx->decrypt.pending != NULL) { serf_bucket_destroy(ssl_ctx->decrypt.pending); @@ -1162,10 +1277,7 @@ SSL_free(ssl_ctx->ssl); SSL_CTX_free(ssl_ctx->ctx); - p = ssl_ctx->pool; - serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx); - apr_pool_destroy(p); return APR_SUCCESS; } @@ -1179,7 +1291,7 @@ ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); if (!ssl_ctx) { - ctx->ssl_ctx = ssl_init_context(); + ctx->ssl_ctx = ssl_init_context(allocator); } else { ctx->ssl_ctx = ssl_ctx; @@ -1206,7 +1318,7 @@ int result = X509_STORE_set_default_paths(store); - return result ? APR_SUCCESS : APR_EGENERAL; + return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED; } apr_status_t serf_ssl_load_cert_file( @@ -1215,7 +1327,7 @@ apr_pool_t *pool) { FILE *fp = fopen(file_path, "r"); - + if (fp) { X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL); fclose(fp); @@ -1228,7 +1340,7 @@ } } - return APR_EGENERAL; + return SERF_ERROR_SSL_CERT_FAILED; } @@ -1240,7 +1352,7 @@ int result = X509_STORE_add_cert(store, cert->ssl_cert); - return result ? APR_SUCCESS : APR_EGENERAL; + return result ? APR_SUCCESS : SERF_ERROR_SSL_CERT_FAILED; } @@ -1521,6 +1633,31 @@ return encoded_cert; } +/* Disables compression for all SSL sessions. */ +static void disable_compression(serf_ssl_context_t *ssl_ctx) +{ +#ifdef SSL_OP_NO_COMPRESSION + SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_NO_COMPRESSION); +#endif +} + +apr_status_t serf_ssl_use_compression(serf_ssl_context_t *ssl_ctx, int enabled) +{ + if (enabled) { +#ifdef SSL_OP_NO_COMPRESSION + SSL_clear_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION); + return APR_SUCCESS; +#endif + } else { +#ifdef SSL_OP_NO_COMPRESSION + SSL_set_options(ssl_ctx->ssl, SSL_OP_NO_COMPRESSION); + return APR_SUCCESS; +#endif + } + + return APR_EGENERAL; +} + static void serf_ssl_destroy_and_data(serf_bucket_t *bucket) { ssl_context_t *ctx = bucket->data; diff -Nru serf-1.1.0/build/apr_common.m4 serf-1.3.3/build/apr_common.m4 --- serf-1.1.0/build/apr_common.m4 2012-06-07 20:24:50.000000000 +0000 +++ serf-1.3.3/build/apr_common.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,985 +0,0 @@ -dnl -------------------------------------------------------- -*- autoconf -*- -dnl Licensed to the Apache Software Foundation (ASF) under one or more -dnl contributor license agreements. See the NOTICE file distributed with -dnl this work for additional information regarding copyright ownership. -dnl The ASF licenses this file to You under the Apache License, Version 2.0 -dnl (the "License"); you may not use this file except in compliance with -dnl the License. You may obtain a copy of the License at -dnl -dnl http://www.apache.org/licenses/LICENSE-2.0 -dnl -dnl Unless required by applicable law or agreed to in writing, software -dnl distributed under the License is distributed on an "AS IS" BASIS, -dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -dnl See the License for the specific language governing permissions and -dnl limitations under the License. - -dnl -dnl apr_common.m4: APR's general-purpose autoconf macros -dnl - -dnl -dnl APR_CONFIG_NICE(filename) -dnl -dnl Saves a snapshot of the configure command-line for later reuse -dnl -AC_DEFUN([APR_CONFIG_NICE], [ - rm -f $1 - cat >$1<> $1 - fi - if test -n "$CFLAGS"; then - echo "CFLAGS=\"$CFLAGS\"; export CFLAGS" >> $1 - fi - if test -n "$CPPFLAGS"; then - echo "CPPFLAGS=\"$CPPFLAGS\"; export CPPFLAGS" >> $1 - fi - if test -n "$LDFLAGS"; then - echo "LDFLAGS=\"$LDFLAGS\"; export LDFLAGS" >> $1 - fi - if test -n "$LTFLAGS"; then - echo "LTFLAGS=\"$LTFLAGS\"; export LTFLAGS" >> $1 - fi - if test -n "$LIBS"; then - echo "LIBS=\"$LIBS\"; export LIBS" >> $1 - fi - if test -n "$INCLUDES"; then - echo "INCLUDES=\"$INCLUDES\"; export INCLUDES" >> $1 - fi - if test -n "$NOTEST_CFLAGS"; then - echo "NOTEST_CFLAGS=\"$NOTEST_CFLAGS\"; export NOTEST_CFLAGS" >> $1 - fi - if test -n "$NOTEST_CPPFLAGS"; then - echo "NOTEST_CPPFLAGS=\"$NOTEST_CPPFLAGS\"; export NOTEST_CPPFLAGS" >> $1 - fi - if test -n "$NOTEST_LDFLAGS"; then - echo "NOTEST_LDFLAGS=\"$NOTEST_LDFLAGS\"; export NOTEST_LDFLAGS" >> $1 - fi - if test -n "$NOTEST_LIBS"; then - echo "NOTEST_LIBS=\"$NOTEST_LIBS\"; export NOTEST_LIBS" >> $1 - fi - - # Retrieve command-line arguments. - eval "set x $[0] $ac_configure_args" - shift - - for arg - do - APR_EXPAND_VAR(arg, $arg) - echo "\"[$]arg\" \\" >> $1 - done - echo '"[$]@"' >> $1 - chmod +x $1 -])dnl - -dnl APR_MKDIR_P_CHECK(fallback-mkdir-p) -dnl checks whether mkdir -p works -AC_DEFUN([APR_MKDIR_P_CHECK], [ - AC_CACHE_CHECK(for working mkdir -p, ac_cv_mkdir_p,[ - test -d conftestdir && rm -rf conftestdir - mkdir -p conftestdir/somedir >/dev/null 2>&1 - if test -d conftestdir/somedir; then - ac_cv_mkdir_p=yes - else - ac_cv_mkdir_p=no - fi - rm -rf conftestdir - ]) - if test "$ac_cv_mkdir_p" = "yes"; then - mkdir_p="mkdir -p" - else - mkdir_p="$1" - fi -]) - -dnl -dnl APR_SUBDIR_CONFIG(dir [, sub-package-cmdline-args, args-to-drop]) -dnl -dnl dir: directory to find configure in -dnl sub-package-cmdline-args: arguments to add to the invocation (optional) -dnl args-to-drop: arguments to drop from the invocation (optional) -dnl -dnl Note: This macro relies on ac_configure_args being set properly. -dnl -dnl The args-to-drop argument is shoved into a case statement, so -dnl multiple arguments can be separated with a |. -dnl -dnl Note: Older versions of autoconf do not single-quote args, while 2.54+ -dnl places quotes around every argument. So, if you want to drop the -dnl argument called --enable-layout, you must pass the third argument as: -dnl [--enable-layout=*|\'--enable-layout=*] -dnl -dnl Trying to optimize this is left as an exercise to the reader who wants -dnl to put up with more autoconf craziness. I give up. -dnl -AC_DEFUN([APR_SUBDIR_CONFIG], [ - # save our work to this point; this allows the sub-package to use it - AC_CACHE_SAVE - - echo "configuring package in $1 now" - ac_popdir=`pwd` - apr_config_subdirs="$1" - test -d $1 || $mkdir_p $1 - ac_abs_srcdir=`(cd $srcdir/$1 && pwd)` - cd $1 - -changequote(, )dnl - # A "../" for each directory in /$config_subdirs. - ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` -changequote([, ])dnl - - # Make the cache file pathname absolute for the subdirs - # required to correctly handle subdirs that might actually - # be symlinks - case "$cache_file" in - /*) # already absolute - ac_sub_cache_file=$cache_file ;; - *) # Was relative path. - ac_sub_cache_file="$ac_popdir/$cache_file" ;; - esac - - ifelse($3, [], [apr_configure_args=$ac_configure_args],[ - apr_configure_args= - apr_sep= - for apr_configure_arg in $ac_configure_args - do - case "$apr_configure_arg" in - $3) - continue ;; - esac - apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'" - apr_sep=" " - done - ]) - - dnl autoconf doesn't add --silent to ac_configure_args; explicitly pass it - test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" - - dnl AC_CONFIG_SUBDIRS silences option warnings, emulate this for 2.62 - apr_configure_args="--disable-option-checking $apr_configure_args" - - dnl The eval makes quoting arguments work - specifically the second argument - dnl where the quoting mechanisms used is "" rather than []. - dnl - dnl We need to execute another shell because some autoconf/shell combinations - dnl will choke after doing repeated APR_SUBDIR_CONFIG()s. (Namely Solaris - dnl and autoconf-2.54+) - if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir $2 - then : - echo "$1 configured properly" - else - echo "configure failed for $1" - exit 1 - fi - - cd $ac_popdir - - # grab any updates from the sub-package - AC_CACHE_LOAD -])dnl - -dnl -dnl APR_SAVE_THE_ENVIRONMENT(variable_name) -dnl -dnl Stores the variable (usually a Makefile macro) for later restoration -dnl -AC_DEFUN([APR_SAVE_THE_ENVIRONMENT], [ - apr_ste_save_$1="$$1" -])dnl - -dnl -dnl APR_RESTORE_THE_ENVIRONMENT(variable_name, prefix_) -dnl -dnl Uses the previously saved variable content to figure out what configure -dnl has added to the variable, moving the new bits to prefix_variable_name -dnl and restoring the original variable contents. This makes it possible -dnl for a user to override configure when it does something stupid. -dnl -AC_DEFUN([APR_RESTORE_THE_ENVIRONMENT], [ -dnl Check whether $apr_ste_save_$1 is empty or -dnl only whitespace. The verbatim "X" is token number 1, -dnl the following whitespace will be ignored. -set X $apr_ste_save_$1 -if test ${#} -eq 1; then - $2$1="$$1" - $1= -else - if test "x$apr_ste_save_$1" = "x$$1"; then - $2$1= - else - $2$1=`echo "$$1" | sed -e "s%${apr_ste_save_$1}%%"` - $1="$apr_ste_save_$1" - fi -fi -if test "x$silent" != "xyes"; then - echo " restoring $1 to \"$$1\"" - echo " setting $2$1 to \"$$2$1\"" -fi -AC_SUBST($2$1) -])dnl - -dnl -dnl APR_SETIFNULL(variable, value) -dnl -dnl Set variable iff it's currently null -dnl -AC_DEFUN([APR_SETIFNULL], [ - if test -z "$$1"; then - test "x$silent" != "xyes" && echo " setting $1 to \"$2\"" - $1="$2" - fi -])dnl - -dnl -dnl APR_SETVAR(variable, value) -dnl -dnl Set variable no matter what -dnl -AC_DEFUN([APR_SETVAR], [ - test "x$silent" != "xyes" && echo " forcing $1 to \"$2\"" - $1="$2" -])dnl - -dnl -dnl APR_ADDTO(variable, value) -dnl -dnl Add value to variable -dnl -AC_DEFUN([APR_ADDTO], [ - if test "x$$1" = "x"; then - test "x$silent" != "xyes" && echo " setting $1 to \"$2\"" - $1="$2" - else - apr_addto_bugger="$2" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $$1; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to $1" - $1="$$1 $i" - fi - done - fi -])dnl - -dnl -dnl APR_REMOVEFROM(variable, value) -dnl -dnl Remove a value from a variable -dnl -AC_DEFUN([APR_REMOVEFROM], [ - if test "x$$1" = "x$2"; then - test "x$silent" != "xyes" && echo " nulling $1" - $1="" - else - apr_new_bugger="" - apr_removed=0 - for i in $$1; do - if test "x$i" != "x$2"; then - apr_new_bugger="$apr_new_bugger $i" - else - apr_removed=1 - fi - done - if test $apr_removed = "1"; then - test "x$silent" != "xyes" && echo " removed \"$2\" from $1" - $1=$apr_new_bugger - fi - fi -]) dnl - -dnl -dnl APR_CHECK_DEFINE_FILES( symbol, header_file [header_file ...] ) -dnl -AC_DEFUN([APR_CHECK_DEFINE_FILES], [ - AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[ - ac_cv_define_$1=no - for curhdr in $2 - do - AC_EGREP_CPP(YES_IS_DEFINED, [ -#include <$curhdr> -#ifdef $1 -YES_IS_DEFINED -#endif - ], ac_cv_define_$1=yes) - done - ]) - if test "$ac_cv_define_$1" = "yes"; then - AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined]) - fi -]) - - -dnl -dnl APR_CHECK_DEFINE(symbol, header_file) -dnl -AC_DEFUN([APR_CHECK_DEFINE], [ - AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[ - AC_EGREP_CPP(YES_IS_DEFINED, [ -#include <$2> -#ifdef $1 -YES_IS_DEFINED -#endif - ], ac_cv_define_$1=yes, ac_cv_define_$1=no) - ]) - if test "$ac_cv_define_$1" = "yes"; then - AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined in $2]) - fi -]) - -dnl -dnl APR_CHECK_APR_DEFINE( symbol ) -dnl -AC_DEFUN([APR_CHECK_APR_DEFINE], [ -apr_old_cppflags=$CPPFLAGS -CPPFLAGS="$CPPFLAGS $INCLUDES" -AC_EGREP_CPP(YES_IS_DEFINED, [ -#include -#if $1 -YES_IS_DEFINED -#endif -], ac_cv_define_$1=yes, ac_cv_define_$1=no) -CPPFLAGS=$apr_old_cppflags -]) - -dnl APR_CHECK_FILE(filename); set ac_cv_file_filename to -dnl "yes" if 'filename' is readable, else "no". -dnl @deprecated! - use AC_CHECK_FILE instead -AC_DEFUN([APR_CHECK_FILE], [ -dnl Pick a safe variable name -define([apr_cvname], ac_cv_file_[]translit([$1], [./+-], [__p_])) -AC_CACHE_CHECK([for $1], [apr_cvname], -[if test -r $1; then - apr_cvname=yes - else - apr_cvname=no - fi]) -]) - -define(APR_IFALLYES,[dnl -ac_rc=yes -for ac_spec in $1; do - ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'` - ac_item=`echo "$ac_spec" | sed -e 's/^.*://'` - case $ac_type in - header ) - ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'` - ac_var="ac_cv_header_$ac_item" - ;; - file ) - ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'` - ac_var="ac_cv_file_$ac_item" - ;; - func ) ac_var="ac_cv_func_$ac_item" ;; - struct ) ac_var="ac_cv_struct_$ac_item" ;; - define ) ac_var="ac_cv_define_$ac_item" ;; - custom ) ac_var="$ac_item" ;; - esac - eval "ac_val=\$$ac_var" - if test ".$ac_val" != .yes; then - ac_rc=no - break - fi -done -if test ".$ac_rc" = .yes; then - : - $2 -else - : - $3 -fi -]) - - -define(APR_BEGIN_DECISION,[dnl -ac_decision_item='$1' -ac_decision_msg='FAILED' -ac_decision='' -]) - - -AC_DEFUN([APR_DECIDE],[dnl -dnl Define the flag (or not) in apr_private.h via autoheader -AH_TEMPLATE($1, [Define if $2 will be used]) -ac_decision='$1' -ac_decision_msg='$2' -ac_decision_$1=yes -ac_decision_$1_msg='$2' -]) - - -define(APR_DECISION_OVERRIDE,[dnl - ac_decision='' - for ac_item in $1; do - eval "ac_decision_this=\$ac_decision_${ac_item}" - if test ".$ac_decision_this" = .yes; then - ac_decision=$ac_item - eval "ac_decision_msg=\$ac_decision_${ac_item}_msg" - fi - done -]) - - -define(APR_DECISION_FORCE,[dnl -ac_decision="$1" -eval "ac_decision_msg=\"\$ac_decision_${ac_decision}_msg\"" -]) - - -define(APR_END_DECISION,[dnl -if test ".$ac_decision" = .; then - echo "[$]0:Error: decision on $ac_decision_item failed" 1>&2 - exit 1 -else - if test ".$ac_decision_msg" = .; then - ac_decision_msg="$ac_decision" - fi - AC_DEFINE_UNQUOTED(${ac_decision_item}) - AC_MSG_RESULT([decision on $ac_decision_item... $ac_decision_msg]) -fi -]) - - -dnl -dnl APR_CHECK_SIZEOF_EXTENDED(INCLUDES, TYPE [, CROSS_SIZE]) -dnl -dnl A variant of AC_CHECK_SIZEOF which allows the checking of -dnl sizes of non-builtin types -dnl -AC_DEFUN([APR_CHECK_SIZEOF_EXTENDED], -[changequote(<<, >>)dnl -dnl The name to #define. -define(<>, translit(sizeof_$2, [a-z *], [A-Z_P]))dnl -dnl The cache variable name. -define(<>, translit(ac_cv_sizeof_$2, [ *], [_p]))dnl -changequote([, ])dnl -AC_MSG_CHECKING(size of $2) -AC_CACHE_VAL(AC_CV_NAME, -[AC_TRY_RUN([#include -$1 -main() -{ - FILE *f=fopen("conftestval", "w"); - if (!f) exit(1); - fprintf(f, "%d\n", sizeof($2)); - exit(0); -}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$3],,, -AC_CV_NAME=$3))])dnl -AC_MSG_RESULT($AC_CV_NAME) -AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The size of ]$2) -undefine([AC_TYPE_NAME])dnl -undefine([AC_CV_NAME])dnl -]) - - -dnl -dnl APR_TRY_COMPILE_NO_WARNING(INCLUDES, FUNCTION-BODY, -dnl [ACTIONS-IF-NO-WARNINGS], [ACTIONS-IF-WARNINGS]) -dnl -dnl Tries a compile test with warnings activated so that the result -dnl is false if the code doesn't compile cleanly. For compilers -dnl where it is not known how to activate a "fail-on-error" mode, -dnl it is undefined which of the sets of actions will be run. -dnl -AC_DEFUN([APR_TRY_COMPILE_NO_WARNING], -[apr_save_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS $CFLAGS_WARN" - if test "$ac_cv_prog_gcc" = "yes"; then - CFLAGS="$CFLAGS -Werror" - fi - AC_COMPILE_IFELSE( - [AC_LANG_SOURCE( - [#include "confdefs.h" - ] - [[$1]] - [int main(int argc, const char *const *argv) {] - [[$2]] - [ return 0; }] - )], - [$3], [$4]) - CFLAGS=$apr_save_CFLAGS -]) - -dnl -dnl APR_CHECK_STRERROR_R_RC -dnl -dnl Decide which style of retcode is used by this system's -dnl strerror_r(). It either returns int (0 for success, -1 -dnl for failure), or it returns a pointer to the error -dnl string. -dnl -dnl -AC_DEFUN([APR_CHECK_STRERROR_R_RC], [ -AC_MSG_CHECKING(for type of return code from strerror_r) -AC_TRY_RUN([ -#include -#include -#include -main() -{ - char buf[1024]; - if (strerror_r(ERANGE, buf, sizeof buf) < 1) { - exit(0); - } - else { - exit(1); - } -}], [ - ac_cv_strerror_r_rc_int=yes ], [ - ac_cv_strerror_r_rc_int=no ], [ - ac_cv_strerror_r_rc_int=no ] ) -if test "x$ac_cv_strerror_r_rc_int" = xyes; then - AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int]) - msg="int" -else - msg="pointer" -fi -AC_MSG_RESULT([$msg]) -] ) - -dnl -dnl APR_CHECK_DIRENT_INODE -dnl -dnl Decide if d_fileno or d_ino are available in the dirent -dnl structure on this platform. Single UNIX Spec says d_ino, -dnl BSD uses d_fileno. Undef to find the real beast. -dnl -AC_DEFUN([APR_CHECK_DIRENT_INODE], [ -AC_CACHE_CHECK([for inode member of struct dirent], apr_cv_dirent_inode, [ -apr_cv_dirent_inode=no -AC_TRY_COMPILE([ -#include -#include -],[ -#ifdef d_ino -#undef d_ino -#endif -struct dirent de; de.d_fileno; -], apr_cv_dirent_inode=d_fileno) -if test "$apr_cv_dirent_inode" = "no"; then -AC_TRY_COMPILE([ -#include -#include -],[ -#ifdef d_fileno -#undef d_fileno -#endif -struct dirent de; de.d_ino; -], apr_cv_dirent_inode=d_ino) -fi -]) -if test "$apr_cv_dirent_inode" != "no"; then - AC_DEFINE_UNQUOTED(DIRENT_INODE, $apr_cv_dirent_inode, - [Define if struct dirent has an inode member]) -fi -]) - -dnl -dnl APR_CHECK_DIRENT_TYPE -dnl -dnl Decide if d_type is available in the dirent structure -dnl on this platform. Not part of the Single UNIX Spec. -dnl Note that this is worthless without DT_xxx macros, so -dnl look for one while we are at it. -dnl -AC_DEFUN([APR_CHECK_DIRENT_TYPE], [ -AC_CACHE_CHECK([for file type member of struct dirent], apr_cv_dirent_type,[ -apr_cv_dirent_type=no -AC_TRY_COMPILE([ -#include -#include -],[ -struct dirent de; de.d_type = DT_REG; -], apr_cv_dirent_type=d_type) -]) -if test "$apr_cv_dirent_type" != "no"; then - AC_DEFINE_UNQUOTED(DIRENT_TYPE, $apr_cv_dirent_type, - [Define if struct dirent has a d_type member]) -fi -]) - -dnl the following is a newline, a space, a tab, and a backslash (the -dnl backslash is used by the shell to skip newlines, but m4 sees it; -dnl treat it like whitespace). -dnl WARNING: don't reindent these lines, or the space/tab will be lost! -define([apr_whitespace],[ - \]) - -dnl -dnl APR_COMMA_ARGS(ARG1 ...) -dnl convert the whitespace-separated arguments into comman-separated -dnl arguments. -dnl -dnl APR_FOREACH(CODE-BLOCK, ARG1, ARG2, ...) -dnl subsitute CODE-BLOCK for each ARG[i]. "eachval" will be set to ARG[i] -dnl within each iteration. -dnl -changequote({,}) -define({APR_COMMA_ARGS},{patsubst([$}{1],[[}apr_whitespace{]+],[,])}) -define({APR_FOREACH}, - {ifelse($}{2,,, - [define([eachval], - $}{2)$}{1[]APR_FOREACH([$}{1], - builtin([shift], - builtin([shift], $}{@)))])}) -changequote([,]) - -dnl APR_FLAG_HEADERS(HEADER-FILE ... [, FLAG-TO-SET ] [, "yes" ]) -dnl we set FLAG-TO-SET to 1 if we find HEADER-FILE, otherwise we set to 0 -dnl if FLAG-TO-SET is null, we automagically determine it's name -dnl by changing all "/" to "_" in the HEADER-FILE and dropping -dnl all "." and "-" chars. If the 3rd parameter is "yes" then instead of -dnl setting to 1 or 0, we set FLAG-TO-SET to yes or no. -dnl -AC_DEFUN([APR_FLAG_HEADERS], [ -AC_CHECK_HEADERS($1) -for aprt_i in $1 -do - ac_safe=`echo "$aprt_i" | sed 'y%./+-%__p_%'` - aprt_2=`echo "$aprt_i" | sed -e 's%/%_%g' -e 's/\.//g' -e 's/-//g'` - if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,yes,1)" - else - eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,no,0)" - fi -done -]) - -dnl APR_FLAG_FUNCS(FUNC ... [, FLAG-TO-SET] [, "yes" ]) -dnl if FLAG-TO-SET is null, we automagically determine it's name -dnl prepending "have_" to the function name in FUNC, otherwise -dnl we use what's provided as FLAG-TO-SET. If the 3rd parameter -dnl is "yes" then instead of setting to 1 or 0, we set FLAG-TO-SET -dnl to yes or no. -dnl -AC_DEFUN([APR_FLAG_FUNCS], [ -AC_CHECK_FUNCS($1) -for aprt_j in $1 -do - aprt_3="have_$aprt_j" - if eval "test \"`echo '$ac_cv_func_'$aprt_j`\" = yes"; then - eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,yes,1)" - else - eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,no,0)" - fi -done -]) - -dnl Iteratively interpolate the contents of the second argument -dnl until interpolation offers no new result. Then assign the -dnl final result to $1. -dnl -dnl Example: -dnl -dnl foo=1 -dnl bar='${foo}/2' -dnl baz='${bar}/3' -dnl APR_EXPAND_VAR(fraz, $baz) -dnl $fraz is now "1/2/3" -dnl -AC_DEFUN([APR_EXPAND_VAR], [ -ap_last= -ap_cur="$2" -while test "x${ap_cur}" != "x${ap_last}"; -do - ap_last="${ap_cur}" - ap_cur=`eval "echo ${ap_cur}"` -done -$1="${ap_cur}" -]) - -dnl -dnl Removes the value of $3 from the string in $2, strips of any leading -dnl slashes, and returns the value in $1. -dnl -dnl Example: -dnl orig_path="${prefix}/bar" -dnl APR_PATH_RELATIVE(final_path, $orig_path, $prefix) -dnl $final_path now contains "bar" -AC_DEFUN([APR_PATH_RELATIVE], [ -ap_stripped=`echo $2 | sed -e "s#^$3##"` -# check if the stripping was successful -if test "x$2" != "x${ap_stripped}"; then - # it was, so strip of any leading slashes - $1="`echo ${ap_stripped} | sed -e 's#^/*##'`" -else - # it wasn't so return the original - $1="$2" -fi -]) - -dnl APR_HELP_STRING(LHS, RHS) -dnl Autoconf 2.50 can not handle substr correctly. It does have -dnl AC_HELP_STRING, so let's try to call it if we can. -dnl Note: this define must be on one line so that it can be properly returned -dnl as the help string. When using this macro with a multi-line RHS, ensure -dnl that you surround the macro invocation with []s -AC_DEFUN([APR_HELP_STRING], [ifelse(regexp(AC_ACVERSION, 2\.1), -1, AC_HELP_STRING([$1],[$2]),[ ][$1] substr([ ],len($1))[$2])]) - -dnl -dnl APR_LAYOUT(configlayout, layoutname [, extravars]) -dnl -AC_DEFUN([APR_LAYOUT], [ - if test ! -f $srcdir/config.layout; then - echo "** Error: Layout file $srcdir/config.layout not found" - echo "** Error: Cannot use undefined layout '$LAYOUT'" - exit 1 - fi - # Catch layout names including a slash which will otherwise - # confuse the heck out of the sed script. - case $2 in - */*) - echo "** Error: $2 is not a valid layout name" - exit 1 ;; - esac - pldconf=./config.pld - changequote({,}) - sed -e "1s/[ ]*<[lL]ayout[ ]*$2[ ]*>[ ]*//;1t" \ - -e "1,/[ ]*<[lL]ayout[ ]*$2[ ]*>[ ]*/d" \ - -e '/[ ]*<\/Layout>[ ]*/,$d' \ - -e "s/^[ ]*//g" \ - -e "s/:[ ]*/=\'/g" \ - -e "s/[ ]*$/'/g" \ - $1 > $pldconf - layout_name=$2 - if test ! -s $pldconf; then - echo "** Error: unable to find layout $layout_name" - exit 1 - fi - . $pldconf - rm $pldconf - for var in prefix exec_prefix bindir sbindir libexecdir mandir \ - sysconfdir datadir includedir localstatedir runtimedir \ - logfiledir libdir installbuilddir libsuffix $3; do - eval "val=\"\$$var\"" - case $val in - *+) - val=`echo $val | sed -e 's;\+$;;'` - eval "$var=\"\$val\"" - autosuffix=yes - ;; - *) - autosuffix=no - ;; - esac - val=`echo $val | sed -e 's:\(.\)/*$:\1:'` - val=`echo $val | sed -e 's:[\$]\([a-z_]*\):${\1}:g'` - if test "$autosuffix" = "yes"; then - if echo $val | grep apache >/dev/null; then - addtarget=no - else - addtarget=yes - fi - if test "$addtarget" = "yes"; then - val="$val/apache2" - fi - fi - eval "$var='$val'" - done - changequote([,]) -])dnl - -dnl -dnl APR_ENABLE_LAYOUT(default layout name [, extra vars]) -dnl -AC_DEFUN([APR_ENABLE_LAYOUT], [ -AC_ARG_ENABLE(layout, -[ --enable-layout=LAYOUT],[ - LAYOUT=$enableval -]) - -if test -z "$LAYOUT"; then - LAYOUT="$1" -fi -APR_LAYOUT($srcdir/config.layout, $LAYOUT, $2) - -AC_MSG_CHECKING(for chosen layout) -AC_MSG_RESULT($layout_name) -]) - - -dnl -dnl APR_PARSE_ARGUMENTS -dnl a reimplementation of autoconf's argument parser, -dnl used here to allow us to co-exist layouts and argument based -dnl set ups. -AC_DEFUN([APR_PARSE_ARGUMENTS], [ -ac_prev= -# Retrieve the command-line arguments. The eval is needed because -# the arguments are quoted to preserve accuracy. -eval "set x $ac_configure_args" -shift -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - ac_optarg=`expr "x$ac_option" : 'x[[^=]]*=\(.*\)'` - - case $ac_option in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir="$ac_optarg" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir="$ac_optarg" ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir="$ac_optarg" ;; - - esac -done - -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [[\\/$]]* | ?:[[\\/]]* | NONE | '' ) ;; - *) AC_MSG_ERROR([expected an absolute path for --$ac_var: $ac_val]);; - esac -done - -])dnl - -dnl -dnl APR_CHECK_DEPEND -dnl -dnl Determine what program we can use to generate .deps-style dependencies -dnl -AC_DEFUN([APR_CHECK_DEPEND], [ -dnl Try to determine what depend program we can use -dnl All GCC-variants should have -MM. -dnl If not, then we can check on those, too. -if test "$GCC" = "yes"; then - MKDEP='$(CC) -MM' -else - rm -f conftest.c -dnl should be available everywhere! - cat > conftest.c < - int main() { return 0; } -EOF - MKDEP="true" - for i in "$CC -MM" "$CC -M" "$CPP -MM" "$CPP -M" "cpp -M"; do - AC_MSG_CHECKING([if $i can create proper make dependencies]) - if $i conftest.c 2>/dev/null | grep 'conftest.o: conftest.c' >/dev/null; then - MKDEP=$i - AC_MSG_RESULT(yes) - break; - fi - AC_MSG_RESULT(no) - done - rm -f conftest.c -fi - -AC_SUBST(MKDEP) -]) - -dnl -dnl APR_CHECK_TYPES_COMPATIBLE(TYPE-1, TYPE-2, [ACTION-IF-TRUE]) -dnl -dnl Try to determine whether two types are the same. Only works -dnl for gcc and icc. -dnl -AC_DEFUN([APR_CHECK_TYPES_COMPATIBLE], [ -define([apr_cvname], apr_cv_typematch_[]translit([$1], [ ], [_])_[]translit([$2], [ ], [_])) -AC_CACHE_CHECK([whether $1 and $2 are the same], apr_cvname, [ -AC_TRY_COMPILE(AC_INCLUDES_DEFAULT, [ - int foo[0 - !__builtin_types_compatible_p($1, $2)]; -], [apr_cvname=yes -$3], [apr_cvname=no])]) -]) diff -Nru serf-1.1.0/build/check.py serf-1.3.3/build/check.py --- serf-1.1.0/build/check.py 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/build/check.py 2013-08-05 08:05:20.000000000 +0000 @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# check.py : Run all the test cases. +# +# ==================================================================== +# Copyright 2013 Justin Erenkrantz and Greg Stein +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ==================================================================== + +import sys +import glob +import subprocess +import os + + +if __name__ == '__main__': + # get the test directory from the commandline, if set. + if len(sys.argv) > 1: + testdir = sys.argv[1] + else: + testdir = 'test' + + # define test executable paths + if sys.platform == 'win32': + SERF_RESPONSE_EXE = 'serf_response.exe' + TEST_ALL_EXE = 'test_all.exe' + else: + SERF_RESPONSE_EXE = 'serf_response' + TEST_ALL_EXE = 'test_all' + SERF_RESPONSE_EXE = os.path.join(testdir, SERF_RESPONSE_EXE) + TEST_ALL_EXE = os.path.join(testdir, TEST_ALL_EXE) + + # Find test responses and run them one by one + for case in glob.glob(testdir + "/testcases/*.response"): + print "== Testing %s ==" % (case) + try: + subprocess.check_call([SERF_RESPONSE_EXE, case]) + except subprocess.CalledProcessError: + print "ERROR: test case %s failed" % (case) + sys.exit(1) + + print "== Running the unit tests ==" + try: + subprocess.check_call(TEST_ALL_EXE) + except subprocess.CalledProcessError: + print "ERROR: test(s) failed in test_all" + sys.exit(1) diff -Nru serf-1.1.0/build/config.guess serf-1.3.3/build/config.guess --- serf-1.1.0/build/config.guess 2012-06-07 20:24:50.000000000 +0000 +++ serf-1.3.3/build/config.guess 1970-01-01 00:00:00.000000000 +0000 @@ -1,1517 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-05-11' - -# This file 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 2 of the License, 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., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-tilera-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff -Nru serf-1.1.0/build/config.sub serf-1.3.3/build/config.sub --- serf-1.1.0/build/config.sub 2012-06-07 20:24:50.000000000 +0000 +++ serf-1.3.3/build/config.sub 1970-01-01 00:00:00.000000000 +0000 @@ -1,1760 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011 Free Software Foundation, Inc. - -timestamp='2011-03-23' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file 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 2 of the License, 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., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free -Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | picochip) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile-* | tilegx-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - # This must be matched before tile*. - tilegx*) - basic_machine=tilegx-unknown - os=-linux-gnu - ;; - tile*) - basic_machine=tile-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff -Nru serf-1.1.0/build/find_apr.m4 serf-1.3.3/build/find_apr.m4 --- serf-1.1.0/build/find_apr.m4 2012-06-07 20:24:50.000000000 +0000 +++ serf-1.3.3/build/find_apr.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -dnl -------------------------------------------------------- -*- autoconf -*- -dnl Licensed to the Apache Software Foundation (ASF) under one or more -dnl contributor license agreements. See the NOTICE file distributed with -dnl this work for additional information regarding copyright ownership. -dnl The ASF licenses this file to You under the Apache License, Version 2.0 -dnl (the "License"); you may not use this file except in compliance with -dnl the License. You may obtain a copy of the License at -dnl -dnl http://www.apache.org/licenses/LICENSE-2.0 -dnl -dnl Unless required by applicable law or agreed to in writing, software -dnl distributed under the License is distributed on an "AS IS" BASIS, -dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -dnl See the License for the specific language governing permissions and -dnl limitations under the License. - -dnl -dnl find_apr.m4 : locate the APR include files and libraries -dnl -dnl This macro file can be used by applications to find and use the APR -dnl library. It provides a standardized mechanism for using APR. It supports -dnl embedding APR into the application source, or locating an installed -dnl copy of APR. -dnl -dnl APR_FIND_APR(srcdir, builddir, implicit-install-check, acceptable-majors, -dnl detailed-check) -dnl -dnl where srcdir is the location of the bundled APR source directory, or -dnl empty if source is not bundled. -dnl -dnl where builddir is the location where the bundled APR will will be built, -dnl or empty if the build will occur in the srcdir. -dnl -dnl where implicit-install-check set to 1 indicates if there is no -dnl --with-apr option specified, we will look for installed copies. -dnl -dnl where acceptable-majors is a space separated list of acceptable major -dnl version numbers. Often only a single major version will be acceptable. -dnl If multiple versions are specified, and --with-apr=PREFIX or the -dnl implicit installed search are used, then the first (leftmost) version -dnl in the list that is found will be used. Currently defaults to [0 1]. -dnl -dnl where detailed-check is an M4 macro which sets the apr_acceptable to -dnl either "yes" or "no". The macro will be invoked for each installed -dnl copy of APR found, with the apr_config variable set appropriately. -dnl Only installed copies of APR which are considered acceptable by -dnl this macro will be considered found. If no installed copies are -dnl considered acceptable by this macro, apr_found will be set to either -dnl either "no" or "reconfig". -dnl -dnl Sets the following variables on exit: -dnl -dnl apr_found : "yes", "no", "reconfig" -dnl -dnl apr_config : If the apr-config tool exists, this refers to it. If -dnl apr_found is "reconfig", then the bundled directory -dnl should be reconfigured *before* using apr_config. -dnl -dnl Note: this macro file assumes that apr-config has been installed; it -dnl is normally considered a required part of an APR installation. -dnl -dnl If a bundled source directory is available and needs to be (re)configured, -dnl then apr_found is set to "reconfig". The caller should reconfigure the -dnl (passed-in) source directory, placing the result in the build directory, -dnl as appropriate. -dnl -dnl If apr_found is "yes" or "reconfig", then the caller should use the -dnl value of apr_config to fetch any necessary build/link information. -dnl - -AC_DEFUN([APR_FIND_APR], [ - apr_found="no" - - if test "$target_os" = "os2-emx"; then - # Scripts don't pass test -x on OS/2 - TEST_X="test -f" - else - TEST_X="test -x" - fi - - ifelse([$4], [], [ - ifdef(AC_WARNING,AC_WARNING([$0: missing argument 4 (acceptable-majors): Defaulting to APR 0.x then APR 1.x])) - acceptable_majors="0 1"], - [acceptable_majors="$4"]) - - apr_temp_acceptable_apr_config="" - for apr_temp_major in $acceptable_majors - do - case $apr_temp_major in - 0) - apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-config" - ;; - *) - apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-$apr_temp_major-config" - ;; - esac - done - - AC_MSG_CHECKING(for APR) - AC_ARG_WITH(apr, - [ --with-apr=PATH prefix for installed APR or the full path to - apr-config], - [ - if test "$withval" = "no" || test "$withval" = "yes"; then - AC_MSG_ERROR([--with-apr requires a directory or file to be provided]) - fi - - for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config - do - for lookdir in "$withval/bin" "$withval" - do - if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then - apr_config="$lookdir/$apr_temp_apr_config_file" - ifelse([$5], [], [], [ - apr_acceptable="yes" - $5 - if test "$apr_acceptable" != "yes"; then - AC_MSG_WARN([Found APR in $apr_config, but we think it is considered unacceptable]) - continue - fi]) - apr_found="yes" - break 2 - fi - done - done - - if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then - apr_config="$withval" - ifelse([$5], [], [apr_found="yes"], [ - apr_acceptable="yes" - $5 - if test "$apr_acceptable" = "yes"; then - apr_found="yes" - fi]) - fi - - dnl if --with-apr is used, it is a fatal error for its argument - dnl to be invalid - if test "$apr_found" != "yes"; then - AC_MSG_ERROR([the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file.]) - fi - ],[ - dnl If we allow installed copies, check those before using bundled copy. - if test -n "$3" && test "$3" = "1"; then - for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config - do - if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then - apr_config="$apr_temp_apr_config_file" - ifelse([$5], [], [], [ - apr_acceptable="yes" - $5 - if test "$apr_acceptable" != "yes"; then - AC_MSG_WARN([skipped APR at $apr_config, version not acceptable]) - continue - fi]) - apr_found="yes" - break - else - dnl look in some standard places - for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do - if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then - apr_config="$lookdir/bin/$apr_temp_apr_config_file" - ifelse([$5], [], [], [ - apr_acceptable="yes" - $5 - if test "$apr_acceptable" != "yes"; then - AC_MSG_WARN([skipped APR at $apr_config, version not acceptable]) - continue - fi]) - apr_found="yes" - break 2 - fi - done - fi - done - fi - dnl if we have not found anything yet and have bundled source, use that - if test "$apr_found" = "no" && test -d "$1"; then - apr_temp_abs_srcdir="`cd \"$1\" && pwd`" - apr_found="reconfig" - apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apr_version.h\"`" - case $apr_bundled_major in - "") - AC_MSG_ERROR([failed to find major version of bundled APR]) - ;; - 0) - apr_temp_apr_config_file="apr-config" - ;; - *) - apr_temp_apr_config_file="apr-$apr_bundled_major-config" - ;; - esac - if test -n "$2"; then - apr_config="$2/$apr_temp_apr_config_file" - else - apr_config="$1/$apr_temp_apr_config_file" - fi - fi - ]) - - AC_MSG_RESULT($apr_found) -]) diff -Nru serf-1.1.0/build/find_apu.m4 serf-1.3.3/build/find_apu.m4 --- serf-1.1.0/build/find_apu.m4 2012-06-07 20:24:50.000000000 +0000 +++ serf-1.3.3/build/find_apu.m4 1970-01-01 00:00:00.000000000 +0000 @@ -1,211 +0,0 @@ -dnl -------------------------------------------------------- -*- autoconf -*- -dnl Licensed to the Apache Software Foundation (ASF) under one or more -dnl contributor license agreements. See the NOTICE file distributed with -dnl this work for additional information regarding copyright ownership. -dnl The ASF licenses this file to You under the Apache License, Version 2.0 -dnl (the "License"); you may not use this file except in compliance with -dnl the License. You may obtain a copy of the License at -dnl -dnl http://www.apache.org/licenses/LICENSE-2.0 -dnl -dnl Unless required by applicable law or agreed to in writing, software -dnl distributed under the License is distributed on an "AS IS" BASIS, -dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -dnl See the License for the specific language governing permissions and -dnl limitations under the License. - -dnl -dnl find_apu.m4 : locate the APR-util (APU) include files and libraries -dnl -dnl This macro file can be used by applications to find and use the APU -dnl library. It provides a standardized mechanism for using APU. It supports -dnl embedding APU into the application source, or locating an installed -dnl copy of APU. -dnl -dnl APR_FIND_APU(srcdir, builddir, implicit-install-check, acceptable-majors, -dnl detailed-check) -dnl -dnl where srcdir is the location of the bundled APU source directory, or -dnl empty if source is not bundled. -dnl -dnl where builddir is the location where the bundled APU will be built, -dnl or empty if the build will occur in the srcdir. -dnl -dnl where implicit-install-check set to 1 indicates if there is no -dnl --with-apr-util option specified, we will look for installed copies. -dnl -dnl where acceptable-majors is a space separated list of acceptable major -dnl version numbers. Often only a single major version will be acceptable. -dnl If multiple versions are specified, and --with-apr-util=PREFIX or the -dnl implicit installed search are used, then the first (leftmost) version -dnl in the list that is found will be used. Currently defaults to [0 1]. -dnl -dnl where detailed-check is an M4 macro which sets the apu_acceptable to -dnl either "yes" or "no". The macro will be invoked for each installed -dnl copy of APU found, with the apu_config variable set appropriately. -dnl Only installed copies of APU which are considered acceptable by -dnl this macro will be considered found. If no installed copies are -dnl considered acceptable by this macro, apu_found will be set to either -dnl either "no" or "reconfig". -dnl -dnl Sets the following variables on exit: -dnl -dnl apu_found : "yes", "no", "reconfig" -dnl -dnl apu_config : If the apu-config tool exists, this refers to it. If -dnl apu_found is "reconfig", then the bundled directory -dnl should be reconfigured *before* using apu_config. -dnl -dnl Note: this macro file assumes that apr-config has been installed; it -dnl is normally considered a required part of an APR installation. -dnl -dnl Note: At this time, we cannot find *both* a source dir and a build dir. -dnl If both are available, the build directory should be passed to -dnl the --with-apr-util switch. -dnl -dnl Note: the installation layout is presumed to follow the standard -dnl PREFIX/lib and PREFIX/include pattern. If the APU config file -dnl is available (and can be found), then non-standard layouts are -dnl possible, since it will be described in the config file. -dnl -dnl If a bundled source directory is available and needs to be (re)configured, -dnl then apu_found is set to "reconfig". The caller should reconfigure the -dnl (passed-in) source directory, placing the result in the build directory, -dnl as appropriate. -dnl -dnl If apu_found is "yes" or "reconfig", then the caller should use the -dnl value of apu_config to fetch any necessary build/link information. -dnl - -AC_DEFUN([APR_FIND_APU], [ - apu_found="no" - - if test "$target_os" = "os2-emx"; then - # Scripts don't pass test -x on OS/2 - TEST_X="test -f" - else - TEST_X="test -x" - fi - - ifelse([$4], [], - [ - ifdef(AC_WARNING,([$0: missing argument 4 (acceptable-majors): Defaulting to APU 0.x then APU 1.x])) - acceptable_majors="0 1" - ], [acceptable_majors="$4"]) - - apu_temp_acceptable_apu_config="" - for apu_temp_major in $acceptable_majors - do - case $apu_temp_major in - 0) - apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-config" - ;; - *) - apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-$apu_temp_major-config" - ;; - esac - done - - AC_MSG_CHECKING(for APR-util) - AC_ARG_WITH(apr-util, - [ --with-apr-util=PATH prefix for installed APU or the full path to - apu-config], - [ - if test "$withval" = "no" || test "$withval" = "yes"; then - AC_MSG_ERROR([--with-apr-util requires a directory or file to be provided]) - fi - - for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config - do - for lookdir in "$withval/bin" "$withval" - do - if $TEST_X "$lookdir/$apu_temp_apu_config_file"; then - apu_config="$lookdir/$apu_temp_apu_config_file" - ifelse([$5], [], [], [ - apu_acceptable="yes" - $5 - if test "$apu_acceptable" != "yes"; then - AC_MSG_WARN([Found APU in $apu_config, but it is considered unacceptable]) - continue - fi]) - apu_found="yes" - break 2 - fi - done - done - - if test "$apu_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then - apu_config="$withval" - ifelse([$5], [], [apu_found="yes"], [ - apu_acceptable="yes" - $5 - if test "$apu_acceptable" = "yes"; then - apu_found="yes" - fi]) - fi - - dnl if --with-apr-util is used, it is a fatal error for its argument - dnl to be invalid - if test "$apu_found" != "yes"; then - AC_MSG_ERROR([the --with-apr-util parameter is incorrect. It must specify an install prefix, a build directory, or an apu-config file.]) - fi - ],[ - if test -n "$3" && test "$3" = "1"; then - for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config - do - if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then - apu_config="$apu_temp_apu_config_file" - ifelse([$5], [], [], [ - apu_acceptable="yes" - $5 - if test "$apu_acceptable" != "yes"; then - AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable]) - continue - fi]) - apu_found="yes" - break - else - dnl look in some standard places (apparently not in builtin/default) - for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do - if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then - apu_config="$lookdir/bin/$apu_temp_apu_config_file" - ifelse([$5], [], [], [ - apu_acceptable="yes" - $5 - if test "$apu_acceptable" != "yes"; then - AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable]) - continue - fi]) - apu_found="yes" - break 2 - fi - done - fi - done - fi - dnl if we have not found anything yet and have bundled source, use that - if test "$apu_found" = "no" && test -d "$1"; then - apu_temp_abs_srcdir="`cd \"$1\" && pwd`" - apu_found="reconfig" - apu_bundled_major="`sed -n '/#define.*APU_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apu_version.h\"`" - case $apu_bundled_major in - "") - AC_MSG_ERROR([failed to find major version of bundled APU]) - ;; - 0) - apu_temp_apu_config_file="apu-config" - ;; - *) - apu_temp_apu_config_file="apu-$apu_bundled_major-config" - ;; - esac - if test -n "$2"; then - apu_config="$2/$apu_temp_apu_config_file" - else - apu_config="$1/$apu_temp_apu_config_file" - fi - fi - ]) - - AC_MSG_RESULT($apu_found) -]) diff -Nru serf-1.1.0/build/gen_def.py serf-1.3.3/build/gen_def.py --- serf-1.1.0/build/gen_def.py 2011-06-25 22:17:42.000000000 +0000 +++ serf-1.3.3/build/gen_def.py 2013-09-04 20:19:57.000000000 +0000 @@ -38,7 +38,7 @@ # a more complicated example might be: # const type * const * serf_func3(... # -_funcs = re.compile(r'^(?:(?:\w+|\*) )+\*?(serf_[a-z][a-z_0-9]*)\(', +_funcs = re.compile(r'^(?:(?:\w+|\*) )+\*?(serf_[a-z][a-zA-Z_0-9]*)\(', re.MULTILINE) # This regex parses the bucket type definitions which look like: @@ -58,11 +58,19 @@ exports.append(name) return exports +# Blacklist the serf v2 API for now +blacklist = ['serf_connection_switch_protocol', + 'serf_http_protocol_create', + 'serf_http_request_create', + 'serf_https_protocol_create'] if __name__ == '__main__': # run the extraction over each file mentioned import sys print("EXPORTS") + for fname in sys.argv[1:]: - for func in extract_exports(fname): + funclist = extract_exports(fname) + funclist = set(funclist) - set(blacklist) + for func in funclist: print(func) diff -Nru serf-1.1.0/build/get-version.sh serf-1.3.3/build/get-version.sh --- serf-1.1.0/build/get-version.sh 2012-06-07 20:24:50.000000000 +0000 +++ serf-1.3.3/build/get-version.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -#!/bin/sh -# -# extract version numbers from a header file -# -# USAGE: get-version.sh CMD VERSION_HEADER PREFIX -# where CMD is one of: all, major, libtool -# where PREFIX is the prefix to {MAJOR|MINOR|PATCH}_VERSION defines -# -# get-version.sh all returns a dotted version number -# get-version.sh major returns just the major version number -# get-version.sh libtool returns a version "libtool -version-info" format -# - -if test $# != 3; then - echo "USAGE: $0 CMD VERSION_HEADER PREFIX" - echo " where CMD is one of: all, major, libtool" - exit 1 -fi - -major_sed="/#define.*$3_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p" -minor_sed="/#define.*$3_MINOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p" -patch_sed="/#define.*$3_PATCH_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p" -major="`sed -n $major_sed $2`" -minor="`sed -n $minor_sed $2`" -patch="`sed -n $patch_sed $2`" - -if test "$1" = "all"; then - echo ${major}.${minor}.${patch} -elif test "$1" = "major"; then - echo ${major} -elif test "$1" = "libtool"; then - # Yes, ${minor}:${patch}:${minor} is correct due to libtool idiocy. - echo ${minor}:${patch}:${minor} -else - echo "ERROR: unknown version CMD ($1)" - exit 1 -fi diff -Nru serf-1.1.0/build/install.sh serf-1.3.3/build/install.sh --- serf-1.1.0/build/install.sh 2012-06-07 20:24:50.000000000 +0000 +++ serf-1.3.3/build/install.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -#!/bin/sh -## -## install.sh -- install a program, script or datafile -## -## Based on `install-sh' from the X Consortium's X11R5 distribution -## as of 89/12/18 which is freely available. -## Cleaned up for Apache's Autoconf-style Interface (APACI) -## by Ralf S. Engelschall -## -# -# This script falls under the Apache License. -# See http://www.apache.org/docs/LICENSE - - -# -# put in absolute paths if you don't have them in your path; -# or use env. vars. -# -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" - -# -# parse argument line -# -instcmd="$mvprog" -chmodcmd="" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -ext="" -src="" -dst="" -while [ "x$1" != "x" ]; do - case $1 in - -c) instcmd="$cpprog" - shift; continue - ;; - -m) chmodcmd="$chmodprog $2" - shift; shift; continue - ;; - -o) chowncmd="$chownprog $2" - shift; shift; continue - ;; - -g) chgrpcmd="$chgrpprog $2" - shift; shift; continue - ;; - -s) stripcmd="$stripprog" - shift; continue - ;; - -S) stripcmd="$stripprog $2" - shift; shift; continue - ;; - -e) ext="$2" - shift; shift; continue - ;; - *) if [ "x$src" = "x" ]; then - src=$1 - else - dst=$1 - fi - shift; continue - ;; - esac -done -if [ "x$src" = "x" ]; then - echo "install.sh: no input file specified" - exit 1 -fi -if [ "x$dst" = "x" ]; then - echo "install.sh: no destination specified" - exit 1 -fi - -# -# If destination is a directory, append the input filename; if -# your system does not like double slashes in filenames, you may -# need to add some logic -# -if [ -d $dst ]; then - dst="$dst/`basename $src`" -fi - -# Add a possible extension (such as ".exe") to src and dst -src="$src$ext" -dst="$dst$ext" - -# Make a temp file name in the proper directory. -dstdir=`dirname $dst` -dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name -$instcmd $src $dsttmp - -# And set any options; do chmod last to preserve setuid bits -if [ "x$chowncmd" != "x" ]; then $chowncmd $dsttmp; fi -if [ "x$chgrpcmd" != "x" ]; then $chgrpcmd $dsttmp; fi -if [ "x$stripcmd" != "x" ]; then $stripcmd $dsttmp; fi -if [ "x$chmodcmd" != "x" ]; then $chmodcmd $dsttmp; fi - -# Now rename the file to the real destination. -$rmcmd $dst -$mvcmd $dsttmp $dst - -exit 0 - diff -Nru serf-1.1.0/build/serf.def serf-1.3.3/build/serf.def --- serf-1.1.0/build/serf.def 2012-06-07 20:24:51.000000000 +0000 +++ serf-1.3.3/build/serf.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -EXPORTS -serf_error_string -serf_context_create -serf_context_create_ex -serf_event_trigger -serf_context_run -serf_context_prerun -serf_context_set_progress_cb -serf_connection_create -serf_connection_create2 -serf_listener_create -serf_incoming_create -serf_connection_reset -serf_connection_close -serf_connection_set_max_outstanding_requests -serf_connection_set_async_responses -serf_connection_request_create -serf_connection_priority_request_create -serf_request_cancel -serf_request_get_pool -serf_request_get_alloc -serf_request_get_conn -serf_request_set_handler -serf_config_proxy -serf_config_authn_types -serf_config_credentials_callback -serf_context_bucket_socket_create -serf_request_bucket_request_create -serf_bucket_allocator_create -serf_bucket_allocator_get_pool -serf_linebuf_init -serf_linebuf_fetch -serf_debug__record_read -serf_debug__entered_loop -serf_debug__closed_conn -serf_debug__bucket_destroy -serf_debug__bucket_alloc_check -serf_lib_version -serf_bucket_request_create -serf_bucket_request_get_headers -serf_bucket_request_become -serf_bucket_request_set_root -serf_bucket_response_create -serf_bucket_response_status -serf_bucket_response_wait_for_headers -serf_bucket_response_get_headers -serf_bucket_response_set_head -serf_bucket_bwtp_frame_get_channel -serf_bucket_bwtp_frame_get_type -serf_bucket_bwtp_frame_get_phrase -serf_bucket_bwtp_frame_get_headers -serf_bucket_bwtp_channel_open -serf_bucket_bwtp_channel_close -serf_bucket_bwtp_header_create -serf_bucket_bwtp_message_create -serf_bucket_bwtp_incoming_frame_create -serf_bucket_bwtp_incoming_frame_wait_for_headers -serf_bucket_aggregate_cleanup -serf_bucket_aggregate_create -serf_bucket_aggregate_become -serf_bucket_aggregate_prepend -serf_bucket_aggregate_append -serf_bucket_aggregate_hold_open -serf_bucket_aggregate_prepend_iovec -serf_bucket_aggregate_append_iovec -serf_bucket_file_create -serf_bucket_socket_create -serf_bucket_socket_set_read_progress_cb -serf_bucket_simple_create -serf_bucket_simple_copy_create -serf_bucket_mmap_create -serf_bucket_headers_create -serf_bucket_headers_set -serf_bucket_headers_setc -serf_bucket_headers_setn -serf_bucket_headers_setx -serf_bucket_headers_get -serf_bucket_headers_do -serf_bucket_chunk_create -serf_bucket_dechunk_create -serf_bucket_deflate_create -serf_bucket_limit_create -serf_ssl_client_cert_provider_set -serf_ssl_client_cert_password_set -serf_ssl_server_cert_callback_set -serf_ssl_server_cert_chain_callback_set -serf_ssl_use_default_certificates -serf_ssl_set_hostname -serf_ssl_cert_depth -serf_ssl_cert_issuer -serf_ssl_cert_subject -serf_ssl_cert_certificate -serf_ssl_cert_export -serf_ssl_load_cert_file -serf_ssl_trust_cert -serf_bucket_ssl_encrypt_create -serf_bucket_ssl_encrypt_context_get -serf_bucket_ssl_decrypt_create -serf_bucket_ssl_decrypt_context_get -serf_bucket_barrier_create -serf_bucket_iovec_create -serf_bucket_type_request -serf_bucket_type_response -serf_bucket_type_bwtp_frame -serf_bucket_type_bwtp_incoming_frame -serf_bucket_type_aggregate -serf_bucket_type_file -serf_bucket_type_socket -serf_bucket_type_simple -serf_bucket_type_mmap -serf_bucket_type_headers -serf_bucket_type_chunk -serf_bucket_type_dechunk -serf_bucket_type_deflate -serf_bucket_type_limit -serf_bucket_type_ssl_encrypt -serf_bucket_type_ssl_decrypt -serf_bucket_type_barrier -serf_bucket_type_iovec -serf_bucket_create -serf_default_read_iovec -serf_default_read_for_sendfile -serf_default_read_bucket -serf_default_destroy -serf_default_destroy_and_data -serf_bucket_mem_alloc -serf_bucket_mem_calloc -serf_bucket_mem_free -serf_bstrmemdup -serf_bmemdup -serf_bstrdup -serf_util_readline -serf_databuf_init -serf_databuf_read -serf_databuf_readline -serf_databuf_peek diff -Nru serf-1.1.0/build/serf.pc.in serf-1.3.3/build/serf.pc.in --- serf-1.1.0/build/serf.pc.in 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/build/serf.pc.in 2013-10-04 15:11:04.000000000 +0000 @@ -0,0 +1,13 @@ +SERF_MAJOR_VERSION=@MAJOR@ +prefix=@PREFIX@ +exec_prefix=${prefix} +libdir=@LIBDIR@ +includedir=${prefix}/include/@INCLUDE_SUBDIR@ + +Name: serf +Description: HTTP client library +Version: @VERSION@ +Requires.private: libssl libcrypto +Libs: -L${libdir} -lserf-${SERF_MAJOR_VERSION} +Libs.private: @LIBS@ +Cflags: -I${includedir} diff -Nru serf-1.1.0/buildconf serf-1.3.3/buildconf --- serf-1.1.0/buildconf 2010-11-01 21:35:15.000000000 +0000 +++ serf-1.3.3/buildconf 1970-01-01 00:00:00.000000000 +0000 @@ -1,119 +0,0 @@ -#!/bin/sh -# -# Copyright 2005 Justin Erenkrantz and Greg Stein -# Copyright 2005 The Apache Software Foundation or its licensors, as -# applicable. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# -# buildconf: Build the support scripts needed to compile from a -# checked-out version of the source code. - -# set a couple of defaults for where we should be looking for our support libs. -# can be overridden with --with-apr=[dir] and --with-apr-util=[dir] - -apr_src_dir="apr ../apr" -apu_src_dir="apr-util ../apr-util" - -while test $# -gt 0 -do - # Normalize - case "$1" in - -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) optarg= ;; - esac - - case "$1" in - --with-apr=*) - apr_src_dir=$optarg - ;; - esac - - case "$1" in - --with-apr-util=*) - apu_src_dir=$optarg - ;; - esac - - shift -done - -# -# Check to be sure that we have the srclib dependencies checked-out -# - -should_exit=0 -apr_found=0 -apu_found=0 - -for dir in $apr_src_dir -do - if [ -d "${dir}" -a -f "${dir}/build/apr_common.m4" ]; then - echo "found apr source: ${dir}" - apr_src_dir=$dir - apr_found=1 - break - fi -done - -if [ $apr_found -lt 1 ]; then - echo "" - echo "You don't have a copy of the apr source in srclib/apr. " - echo "Please get the source using the following instructions," - echo "or specify the location of the source with " - echo "--with-apr=[path to apr] :" - echo "" - echo " svn co http://svn.apache.org/repos/asf/apr/apr/trunk srclib/apr" - echo "" - should_exit=1 -fi - -for dir in $apu_src_dir -do - if [ -d "${dir}" -a -f "${dir}/Makefile.in" ]; then - echo "found apr-util source: ${dir}" - apu_src_dir=$dir - apu_found=1 - break - fi -done - -if [ $apu_found -lt 1 ]; then - echo "" - echo "APR-util not found. Assuming you are using APR 2.x." - echo "" - apu_src_dir= -fi - -if [ $should_exit -gt 0 ]; then - exit 1 -fi - -echo copying build files -cp $apr_src_dir/build/config.guess $apr_src_dir/build/config.sub \ - $apr_src_dir/build/install.sh $apr_src_dir/build/apr_common.m4 \ - $apr_src_dir/build/find_apr.m4 $apr_src_dir/build/get-version.sh build - -if [ -n "$apu_src_dir" -a -d "$apu_src_dir" ] ; then - cp $apu_src_dir/build/find_apu.m4 build -fi - -echo generating configure -${AUTOCONF:-autoconf} - -# Remove autoconf 2.5x's cache directory -rm -rf autom4te*.cache - -echo generating serf.def -./build/gen_def.py serf.h serf_bucket_*.h > build/serf.def diff -Nru serf-1.1.0/config.layout serf-1.3.3/config.layout --- serf-1.1.0/config.layout 2007-08-26 07:27:48.000000000 +0000 +++ serf-1.3.3/config.layout 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -## -## config.layout -- Pre-defined Installation Path Layouts -## -## Hints: -## - layouts can be loaded with configure's --enable-layout=ID option -## - when no --enable-layout option is given, the default layout is `serf' -## - a trailing plus character (`+') on paths is replaced with a -## `/' suffix where is currently hardcoded to 'serf'. -## (This may become a configurable parameter at some point.) -## - - - prefix: /usr/local/serf - exec_prefix: ${prefix} - bindir: ${exec_prefix}/bin - sbindir: ${exec_prefix}/bin - libdir: ${exec_prefix}/lib - libexecdir: ${exec_prefix}/modules - mandir: ${prefix}/man - sysconfdir: ${prefix}/conf - datadir: ${prefix} - installbuilddir: ${datadir}/build-${SERF_MAJOR_VERSION} - includedir: ${prefix}/include/serf-${SERF_MAJOR_VERSION} - localstatedir: ${prefix} - libsuffix: -${SERF_MAJOR_VERSION} - diff -Nru serf-1.1.0/configure serf-1.3.3/configure --- serf-1.1.0/configure 2012-06-07 20:24:51.000000000 +0000 +++ serf-1.3.3/configure 1970-01-01 00:00:00.000000000 +0000 @@ -1,6257 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61. -# -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -as_nl=' -' -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } -fi - -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# CDPATH. -$as_unset CDPATH - - -if test "x$CONFIG_SHELL" = x; then - if (eval ":") 2>/dev/null; then - as_have_required=yes -else - as_have_required=no -fi - - if test $as_have_required = yes && (eval ": -(as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=\$LINENO - as_lineno_2=\$LINENO - test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && - test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } -") 2> /dev/null; then - : -else - as_candidate_shells= - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - case $as_dir in - /*) - for as_base in sh bash ksh sh5; do - as_candidate_shells="$as_candidate_shells $as_dir/$as_base" - done;; - esac -done -IFS=$as_save_IFS - - - for as_shell in $as_candidate_shells $SHELL; do - # Try only shells that exist, to save several forks. - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { ("$as_shell") 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -_ASEOF -}; then - CONFIG_SHELL=$as_shell - as_have_required=yes - if { "$as_shell" 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -(as_func_return () { - (exit $1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = "$1" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test $exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } - -_ASEOF -}; then - break -fi - -fi - - done - - if test "x$CONFIG_SHELL" != x; then - for as_var in BASH_ENV ENV - do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - done - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} -fi - - - if test $as_have_required = no; then - echo This script requires a shell more modern than all the - echo shells that I found on your system. Please install a - echo modern shell, or manually run the script under such a - echo shell if you do have one. - { (exit 1); exit 1; } -fi - - -fi - -fi - - - -(eval "as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0") || { - echo No shell found that supports shell functions. - echo Please tell autoconf@gnu.org about your system, - echo including any error possibly output before this - echo message -} - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in --n*) - case `echo 'x\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; - esac;; -*) - ECHO_N='-n';; -esac - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir -fi -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - - -exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Identity of this package. -PACKAGE_NAME= -PACKAGE_TARNAME= -PACKAGE_VERSION= -PACKAGE_STRING= -PACKAGE_BUGREPORT= - -ac_unique_file="context.c" -ac_default_prefix=/usr/local/serf -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='SHELL -PATH_SEPARATOR -PACKAGE_NAME -PACKAGE_TARNAME -PACKAGE_VERSION -PACKAGE_STRING -PACKAGE_BUGREPORT -exec_prefix -prefix -program_transform_name -bindir -sbindir -libexecdir -datarootdir -datadir -sysconfdir -sharedstatedir -localstatedir -includedir -oldincludedir -docdir -infodir -htmldir -dvidir -pdfdir -psdir -libdir -localedir -mandir -DEFS -ECHO_C -ECHO_N -ECHO_T -LIBS -build_alias -host_alias -target_alias -mkdir_p -build -build_cpu -build_vendor -build_os -host -host_cpu -host_vendor -host_os -target -target_cpu -target_vendor -target_os -LTFLAGS -APR_LIBTOOL -APR_BINDIR -APR_INCLUDES -APR_VERSION -APR_CONFIG -APU_BINDIR -APU_INCLUDES -APU_VERSION -APU_CONFIG -CC -CFLAGS -LDFLAGS -CPPFLAGS -ac_ct_CC -EXEEXT -OBJEXT -CPP -INSTALL_PROGRAM -INSTALL_SCRIPT -INSTALL_DATA -SERF_MAJOR_VERSION -SERF_DOTTED_VERSION -SERF_BUILD_SRCLIB_DIRS -SERF_CLEAN_SRCLIB_DIRS -GREP -EGREP -SERF_LIBS -EXTRA_CPPFLAGS -EXTRA_CFLAGS -EXTRA_CXXFLAGS -EXTRA_LDFLAGS -EXTRA_LIBS -EXTRA_INCLUDES -LIBOBJS -LTLIBOBJS' -ac_subst_files='' - ac_precious_vars='build_alias -host_alias -target_alias -CC -CFLAGS -LDFLAGS -LIBS -CPPFLAGS -CPP' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` - eval enable_$ac_feature=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` - eval enable_$ac_feature=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/[-.]/_/g'` - eval with_$ac_package=\$ac_optarg ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/[-.]/_/g'` - eval with_$ac_package=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute directory names. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; } -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - { echo "$as_me: error: Working directory cannot be determined" >&2 - { (exit 1); exit 1; }; } -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - { echo "$as_me: error: pwd does not report name of working directory" >&2 - { (exit 1); exit 1; }; } - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$0" || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 - { (exit 1); exit 1; }; } - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures this package to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] - --target=TARGET configure for building compilers for TARGET [HOST] -_ACEOF -fi - -if test -n "$ac_init_help"; then - - cat <<\_ACEOF - -Optional Features: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-layout=LAYOUT - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-apr=PATH prefix for installed APR or the full path to - apr-config - --with-apr-util=PATH prefix for installed APU or the full path to - apu-config - --with-openssl=PATH Path to OpenSSL (eg. /usr/local/ssl) - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CPP C preprocessor - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -configure -generated by GNU Autoconf 2.61 - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by $as_me, which was -generated by GNU Autoconf 2.61. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args '$ac_arg'" - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## -## File substitutions. ## -## ------------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -n "$CONFIG_SITE"; then - set x "$CONFIG_SITE" -elif test "x$prefix" != xNONE; then - set x "$prefix/share/config.site" "$prefix/etc/config.site" -else - set x "$ac_default_prefix/share/config.site" \ - "$ac_default_prefix/etc/config.site" -fi -shift -for ac_site_file -do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - - - - - - - - - - - - - - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -ac_aux_dir= -for ac_dir in build "$srcdir"/build; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in build \"$srcdir\"/build" >&5 -echo "$as_me: error: cannot find install-sh or install.sh in build \"$srcdir\"/build" >&2;} - { (exit 1); exit 1; }; } -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Check whether --enable-layout was given. -if test "${enable_layout+set}" = set; then - enableval=$enable_layout; - LAYOUT=$enableval - -fi - - -if test -z "$LAYOUT"; then - LAYOUT="Serf" -fi - - if test ! -f $srcdir/config.layout; then - echo "** Error: Layout file $srcdir/config.layout not found" - echo "** Error: Cannot use undefined layout '$LAYOUT'" - exit 1 - fi - # Catch layout names including a slash which will otherwise - # confuse the heck out of the sed script. - case $LAYOUT in - */*) - echo "** Error: $LAYOUT is not a valid layout name" - exit 1 ;; - esac - pldconf=./config.pld - - sed -e "1s/[ ]*<[lL]ayout[ ]*$LAYOUT[ ]*>[ ]*//;1t" \ - -e "1,/[ ]*<[lL]ayout[ ]*$LAYOUT[ ]*>[ ]*/d" \ - -e '/[ ]*<\/Layout>[ ]*/,$d' \ - -e "s/^[ ]*//g" \ - -e "s/:[ ]*/=\'/g" \ - -e "s/[ ]*$/'/g" \ - $srcdir/config.layout > $pldconf - layout_name=$LAYOUT - if test ! -s $pldconf; then - echo "** Error: unable to find layout $layout_name" - exit 1 - fi - . $pldconf - rm $pldconf - for var in prefix exec_prefix bindir sbindir libexecdir mandir \ - sysconfdir datadir includedir localstatedir runtimedir \ - logfiledir libdir installbuilddir libsuffix ; do - eval "val=\"\$$var\"" - case $val in - *+) - val=`echo $val | sed -e 's;\+$;;'` - eval "$var=\"\$val\"" - autosuffix=yes - ;; - *) - autosuffix=no - ;; - esac - val=`echo $val | sed -e 's:\(.\)/*$:\1:'` - val=`echo $val | sed -e 's:[\$]\([a-z_]*\):$\1:g'` - if test "$autosuffix" = "yes"; then - if echo $val | grep apache >/dev/null; then - addtarget=no - else - addtarget=yes - fi - if test "$addtarget" = "yes"; then - val="$val/apache2" - fi - fi - eval "$var='$val'" - done - - - -{ echo "$as_me:$LINENO: checking for chosen layout" >&5 -echo $ECHO_N "checking for chosen layout... $ECHO_C" >&6; } -{ echo "$as_me:$LINENO: result: $layout_name" >&5 -echo "${ECHO_T}$layout_name" >&6; } - - - -ac_prev= -# Retrieve the command-line arguments. The eval is needed because -# the arguments are quoted to preserve accuracy. -eval "set x $ac_configure_args" -shift -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` - - case $ac_option in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir="$ac_optarg" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir="$ac_optarg" ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir="$ac_optarg" ;; - - esac -done - -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { { echo "$as_me:$LINENO: error: expected an absolute path for --$ac_var: $ac_val" >&5 -echo "$as_me: error: expected an absolute path for --$ac_var: $ac_val" >&2;} - { (exit 1); exit 1; }; };; - esac -done - - - - - apr_ste_save_CPPFLAGS="$CPPFLAGS" - - - apr_ste_save_CFLAGS="$CFLAGS" - - - apr_ste_save_CXXFLAGS="$CXXFLAGS" - - - apr_ste_save_LDFLAGS="$LDFLAGS" - - - apr_ste_save_LIBS="$LIBS" - - - apr_ste_save_INCLUDES="$INCLUDES" - - - - rm -f config.nice - cat >config.nice<> config.nice - fi - if test -n "$CFLAGS"; then - echo "CFLAGS=\"$CFLAGS\"; export CFLAGS" >> config.nice - fi - if test -n "$CPPFLAGS"; then - echo "CPPFLAGS=\"$CPPFLAGS\"; export CPPFLAGS" >> config.nice - fi - if test -n "$LDFLAGS"; then - echo "LDFLAGS=\"$LDFLAGS\"; export LDFLAGS" >> config.nice - fi - if test -n "$LTFLAGS"; then - echo "LTFLAGS=\"$LTFLAGS\"; export LTFLAGS" >> config.nice - fi - if test -n "$LIBS"; then - echo "LIBS=\"$LIBS\"; export LIBS" >> config.nice - fi - if test -n "$INCLUDES"; then - echo "INCLUDES=\"$INCLUDES\"; export INCLUDES" >> config.nice - fi - if test -n "$NOTEST_CFLAGS"; then - echo "NOTEST_CFLAGS=\"$NOTEST_CFLAGS\"; export NOTEST_CFLAGS" >> config.nice - fi - if test -n "$NOTEST_CPPFLAGS"; then - echo "NOTEST_CPPFLAGS=\"$NOTEST_CPPFLAGS\"; export NOTEST_CPPFLAGS" >> config.nice - fi - if test -n "$NOTEST_LDFLAGS"; then - echo "NOTEST_LDFLAGS=\"$NOTEST_LDFLAGS\"; export NOTEST_LDFLAGS" >> config.nice - fi - if test -n "$NOTEST_LIBS"; then - echo "NOTEST_LIBS=\"$NOTEST_LIBS\"; export NOTEST_LIBS" >> config.nice - fi - - # Retrieve command-line arguments. - eval "set x $0 $ac_configure_args" - shift - - for arg - do - -ap_last= -ap_cur="$arg" -while test "x${ap_cur}" != "x${ap_last}"; -do - ap_last="${ap_cur}" - ap_cur=`eval "echo ${ap_cur}"` -done -arg="${ap_cur}" - - echo "\"$arg\" \\" >> config.nice - done - echo '"$@"' >> config.nice - chmod +x config.nice - - -nl=' -' - - { echo "$as_me:$LINENO: checking for working mkdir -p" >&5 -echo $ECHO_N "checking for working mkdir -p... $ECHO_C" >&6; } -if test "${ac_cv_mkdir_p+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - - test -d conftestdir && rm -rf conftestdir - mkdir -p conftestdir/somedir >/dev/null 2>&1 - if test -d conftestdir/somedir; then - ac_cv_mkdir_p=yes - else - ac_cv_mkdir_p=no - fi - rm -rf conftestdir - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_mkdir_p" >&5 -echo "${ECHO_T}$ac_cv_mkdir_p" >&6; } - if test "$ac_cv_mkdir_p" = "yes"; then - mkdir_p="mkdir -p" - else - mkdir_p="$top_srcdir/build/mkdir.sh" - fi - - - - - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 -echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} - { (exit 1); exit 1; }; } - -{ echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6; } -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 -echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 -echo "$as_me: error: invalid value of canonical build" >&2;} - { (exit 1); exit 1; }; };; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6; } -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 -echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} - { (exit 1); exit 1; }; } -fi - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 -echo "$as_me: error: invalid value of canonical host" >&2;} - { (exit 1); exit 1; }; };; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -{ echo "$as_me:$LINENO: checking target system type" >&5 -echo $ECHO_N "checking target system type... $ECHO_C" >&6; } -if test "${ac_cv_target+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "x$target_alias" = x; then - ac_cv_target=$ac_cv_host -else - ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || - { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 -echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} - { (exit 1); exit 1; }; } -fi - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 -echo "${ECHO_T}$ac_cv_target" >&6; } -case $ac_cv_target in -*-*-*) ;; -*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 -echo "$as_me: error: invalid value of canonical target" >&2;} - { (exit 1); exit 1; }; };; -esac -target=$ac_cv_target -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_target -shift -target_cpu=$1 -target_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -target_os=$* -IFS=$ac_save_IFS -case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac - - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -test -n "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- - -orig_prefix="$prefix" - -echo $ac_n "${nl}Configuring Apache Portable Runtime library...${nl}" - - - apr_found="no" - - if test "$target_os" = "os2-emx"; then - # Scripts don't pass test -x on OS/2 - TEST_X="test -f" - else - TEST_X="test -x" - fi - - acceptable_majors="0 1 2" - - apr_temp_acceptable_apr_config="" - for apr_temp_major in $acceptable_majors - do - case $apr_temp_major in - 0) - apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-config" - ;; - *) - apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-$apr_temp_major-config" - ;; - esac - done - - { echo "$as_me:$LINENO: checking for APR" >&5 -echo $ECHO_N "checking for APR... $ECHO_C" >&6; } - -# Check whether --with-apr was given. -if test "${with_apr+set}" = set; then - withval=$with_apr; - if test "$withval" = "no" || test "$withval" = "yes"; then - { { echo "$as_me:$LINENO: error: --with-apr requires a directory or file to be provided" >&5 -echo "$as_me: error: --with-apr requires a directory or file to be provided" >&2;} - { (exit 1); exit 1; }; } - fi - - for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config - do - for lookdir in "$withval/bin" "$withval" - do - if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then - apr_config="$lookdir/$apr_temp_apr_config_file" - - apr_found="yes" - break 2 - fi - done - done - - if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then - apr_config="$withval" - apr_found="yes" - fi - - if test "$apr_found" != "yes"; then - { { echo "$as_me:$LINENO: error: the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file." >&5 -echo "$as_me: error: the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file." >&2;} - { (exit 1); exit 1; }; } - fi - -else - - if test -n "1" && test "1" = "1"; then - for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config - do - if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then - apr_config="$apr_temp_apr_config_file" - - apr_found="yes" - break - else - for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do - if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then - apr_config="$lookdir/bin/$apr_temp_apr_config_file" - - apr_found="yes" - break 2 - fi - done - fi - done - fi - if test "$apr_found" = "no" && test -d ""$srcdir/apr""; then - apr_temp_abs_srcdir="`cd \""$srcdir/apr"\" && pwd`" - apr_found="reconfig" - apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \""$srcdir/apr"/include/apr_version.h\"`" - case $apr_bundled_major in - "") - { { echo "$as_me:$LINENO: error: failed to find major version of bundled APR" >&5 -echo "$as_me: error: failed to find major version of bundled APR" >&2;} - { (exit 1); exit 1; }; } - ;; - 0) - apr_temp_apr_config_file="apr-config" - ;; - *) - apr_temp_apr_config_file="apr-$apr_bundled_major-config" - ;; - esac - if test -n ""./apr""; then - apr_config=""./apr"/$apr_temp_apr_config_file" - else - apr_config=""$srcdir/apr"/$apr_temp_apr_config_file" - fi - fi - -fi - - - { echo "$as_me:$LINENO: result: $apr_found" >&5 -echo "${ECHO_T}$apr_found" >&6; } - - -if test "$apr_found" = "no"; then - { { echo "$as_me:$LINENO: error: APR not found. Please read the documentation." >&5 -echo "$as_me: error: APR not found. Please read the documentation." >&2;} - { (exit 1); exit 1; }; } -fi - -if test "$apr_found" = "reconfig"; then - - # save our work to this point; this allows the sub-package to use it - cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { echo "$as_me:$LINENO: updating cache $cache_file" >&5 -echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file - else - { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 -echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - - echo "configuring package in apr now" - ac_popdir=`pwd` - apr_config_subdirs="apr" - test -d apr || $mkdir_p apr - ac_abs_srcdir=`(cd $srcdir/apr && pwd)` - cd apr - - # A "../" for each directory in /$config_subdirs. - ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` - - # Make the cache file pathname absolute for the subdirs - # required to correctly handle subdirs that might actually - # be symlinks - case "$cache_file" in - /*) # already absolute - ac_sub_cache_file=$cache_file ;; - *) # Was relative path. - ac_sub_cache_file="$ac_popdir/$cache_file" ;; - esac - - - apr_configure_args= - apr_sep= - for apr_configure_arg in $ac_configure_args - do - case "$apr_configure_arg" in - --enable-layout=*|\'--enable-layout=*) - continue ;; - esac - apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'" - apr_sep=" " - done - - - test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" - - apr_configure_args="--disable-option-checking $apr_configure_args" - - if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir --prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir --datadir=$datadir --with-installbuilddir=$installbuilddir - then : - echo "apr configured properly" - else - echo "configure failed for apr" - exit 1 - fi - - cd $ac_popdir - - # grab any updates from the sub-package - if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - - - SERF_BUILD_SRCLIB_DIRS="apr $SERF_BUILD_SRCLIB_DIRS" - SERF_CLEAN_SRCLIB_DIRS="$SERF_CLEAN_SRCLIB_DIRS apr" -fi - - - if test -z "$CC"; then - test "x$silent" != "xyes" && echo " setting CC to \"`$apr_config --cc`\"" - CC="`$apr_config --cc`" - fi - - - if test -z "$CPP"; then - test "x$silent" != "xyes" && echo " setting CPP to \"`$apr_config --cpp`\"" - CPP="`$apr_config --cpp`" - fi - - - if test -z "$APR_LIBTOOL"; then - test "x$silent" != "xyes" && echo " setting APR_LIBTOOL to \"`$apr_config --apr-libtool`\"" - APR_LIBTOOL="`$apr_config --apr-libtool`" - fi - - - if test "x$CFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting CFLAGS to \"`$apr_config --cflags`\"" - CFLAGS="`$apr_config --cflags`" - else - apr_addto_bugger="`$apr_config --cflags`" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $CFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to CFLAGS" - CFLAGS="$CFLAGS $i" - fi - done - fi - - - if test "x$CPPFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting CPPFLAGS to \"`$apr_config --cppflags`\"" - CPPFLAGS="`$apr_config --cppflags`" - else - apr_addto_bugger="`$apr_config --cppflags`" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $CPPFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to CPPFLAGS" - CPPFLAGS="$CPPFLAGS $i" - fi - done - fi - - - if test "x$LDFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting LDFLAGS to \"`$apr_config --ldflags`\"" - LDFLAGS="`$apr_config --ldflags`" - else - apr_addto_bugger="`$apr_config --ldflags`" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $LDFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" - LDFLAGS="$LDFLAGS $i" - fi - done - fi - -SHLIBPATH_VAR=`$apr_config --shlib-path-var` -APR_BINDIR=`$apr_config --bindir` -APR_INCLUDES=`$apr_config --includes` -APR_VERSION=`$apr_config --version` -APR_CONFIG="$apr_config" - - - if test -z "$LTFLAGS"; then - test "x$silent" != "xyes" && echo " setting LTFLAGS to \""--silent"\"" - LTFLAGS=""--silent"" - fi - - - - - - - - - -APR_VERSION_MAJOR="`echo \"$APR_VERSION\" | sed 's,\..*,,'`" -APR_VERSION_NUM="`echo \"$APR_VERSION\" | \ - sed -e 's/[^0-9\.].*$//' \ - -e 's/\.\([0-9]\)$/.0\1/' \ - -e 's/\.\([0-9][0-9]\)$/.0\1/' \ - -e 's/\.\([0-9]\)\./0\1/; s/\.//g;'`" - -if test "$APR_VERSION_NUM" -ge "200000"; then - - APU_BINDIR="" - APU_INCLUDES="" - APU_VERSION="" - APU_CONFIG="" - -else - - - - - - echo $ac_n "${nl}Configuring Apache Portable Runtime Utility library...${nl}" - - - - apu_found="no" - - if test "$target_os" = "os2-emx"; then - # Scripts don't pass test -x on OS/2 - TEST_X="test -f" - else - TEST_X="test -x" - fi - - acceptable_majors="$APR_VERSION_MAJOR" - - apu_temp_acceptable_apu_config="" - for apu_temp_major in $acceptable_majors - do - case $apu_temp_major in - 0) - apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-config" - ;; - *) - apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-$apu_temp_major-config" - ;; - esac - done - - { echo "$as_me:$LINENO: checking for APR-util" >&5 -echo $ECHO_N "checking for APR-util... $ECHO_C" >&6; } - -# Check whether --with-apr-util was given. -if test "${with_apr_util+set}" = set; then - withval=$with_apr_util; - if test "$withval" = "no" || test "$withval" = "yes"; then - { { echo "$as_me:$LINENO: error: --with-apr-util requires a directory or file to be provided" >&5 -echo "$as_me: error: --with-apr-util requires a directory or file to be provided" >&2;} - { (exit 1); exit 1; }; } - fi - - for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config - do - for lookdir in "$withval/bin" "$withval" - do - if $TEST_X "$lookdir/$apu_temp_apu_config_file"; then - apu_config="$lookdir/$apu_temp_apu_config_file" - - apu_found="yes" - break 2 - fi - done - done - - if test "$apu_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then - apu_config="$withval" - apu_found="yes" - fi - - if test "$apu_found" != "yes"; then - { { echo "$as_me:$LINENO: error: the --with-apr-util parameter is incorrect. It must specify an install prefix, a build directory, or an apu-config file." >&5 -echo "$as_me: error: the --with-apr-util parameter is incorrect. It must specify an install prefix, a build directory, or an apu-config file." >&2;} - { (exit 1); exit 1; }; } - fi - -else - - if test -n "1" && test "1" = "1"; then - for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config - do - if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then - apu_config="$apu_temp_apu_config_file" - - apu_found="yes" - break - else - for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do - if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then - apu_config="$lookdir/bin/$apu_temp_apu_config_file" - - apu_found="yes" - break 2 - fi - done - fi - done - fi - if test "$apu_found" = "no" && test -d ""$srcdir/apr-util""; then - apu_temp_abs_srcdir="`cd \""$srcdir/apr-util"\" && pwd`" - apu_found="reconfig" - apu_bundled_major="`sed -n '/#define.*APU_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \""$srcdir/apr-util"/include/apu_version.h\"`" - case $apu_bundled_major in - "") - { { echo "$as_me:$LINENO: error: failed to find major version of bundled APU" >&5 -echo "$as_me: error: failed to find major version of bundled APU" >&2;} - { (exit 1); exit 1; }; } - ;; - 0) - apu_temp_apu_config_file="apu-config" - ;; - *) - apu_temp_apu_config_file="apu-$apu_bundled_major-config" - ;; - esac - if test -n ""./apr-util""; then - apu_config=""./apr-util"/$apu_temp_apu_config_file" - else - apu_config=""$srcdir/apr-util"/$apu_temp_apu_config_file" - fi - fi - -fi - - - { echo "$as_me:$LINENO: result: $apu_found" >&5 -echo "${ECHO_T}$apu_found" >&6; } - - - - if test "$apu_found" = "no"; then - { { echo "$as_me:$LINENO: error: APR-util not found. Please read the documentation." >&5 -echo "$as_me: error: APR-util not found. Please read the documentation." >&2;} - { (exit 1); exit 1; }; } - fi - - # Catch some misconfigurations: - case ${apr_found}.${apu_found} in - reconfig.yes) - { { echo "$as_me:$LINENO: error: Cannot use an external APR-util with the bundled APR" >&5 -echo "$as_me: error: Cannot use an external APR-util with the bundled APR" >&2;} - { (exit 1); exit 1; }; } - ;; - yes.reconfig) - { { echo "$as_me:$LINENO: error: Cannot use an external APR with the bundled APR-util" >&5 -echo "$as_me: error: Cannot use an external APR with the bundled APR-util" >&2;} - { (exit 1); exit 1; }; } - ;; - esac - - if test "$apu_found" = "reconfig"; then - - # save our work to this point; this allows the sub-package to use it - cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { echo "$as_me:$LINENO: updating cache $cache_file" >&5 -echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file - else - { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 -echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - - echo "configuring package in apr-util now" - ac_popdir=`pwd` - apr_config_subdirs="apr-util" - test -d apr-util || $mkdir_p apr-util - ac_abs_srcdir=`(cd $srcdir/apr-util && pwd)` - cd apr-util - - # A "../" for each directory in /$config_subdirs. - ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` - - # Make the cache file pathname absolute for the subdirs - # required to correctly handle subdirs that might actually - # be symlinks - case "$cache_file" in - /*) # already absolute - ac_sub_cache_file=$cache_file ;; - *) # Was relative path. - ac_sub_cache_file="$ac_popdir/$cache_file" ;; - esac - - - apr_configure_args= - apr_sep= - for apr_configure_arg in $ac_configure_args - do - case "$apr_configure_arg" in - --enable-layout=*|\'--enable-layout=*) - continue ;; - esac - apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'" - apr_sep=" " - done - - - test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" - - apr_configure_args="--disable-option-checking $apr_configure_args" - - if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir --with-apr=../apr --prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir - then : - echo "apr-util configured properly" - else - echo "configure failed for apr-util" - exit 1 - fi - - cd $ac_popdir - - # grab any updates from the sub-package - if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - - - SERF_BUILD_SRCLIB_DIRS="$SERF_BUILD_SRCLIB_DIRS apr-util" - SERF_CLEAN_SRCLIB_DIRS="apr-util $SERF_CLEAN_SRCLIB_DIRS" - fi - - - if test "x$LDFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting LDFLAGS to \"`$apu_config --ldflags`\"" - LDFLAGS="`$apu_config --ldflags`" - else - apr_addto_bugger="`$apu_config --ldflags`" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $LDFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" - LDFLAGS="$LDFLAGS $i" - fi - done - fi - - APU_BINDIR=`$apu_config --bindir` - APU_INCLUDES=`$apu_config --includes` - APU_VERSION=`$apu_config --version` - APU_CONFIG="$APU_BINDIR/apu-`echo ${APU_VERSION} | sed 's,\..*,,'`-config" -fi - - - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - -# Provide some information about the compiler. -echo "$as_me:$LINENO: checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (ac_try="$ac_compiler --version >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler --version >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -v >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -v >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -V >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -V >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -# -# List of possible output files, starting from the most likely. -# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) -# only as a last resort. b.out is created by i960 compilers. -ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' -# -# The IRIX 6 linker writes into existing files which may not be -# executable, retaining their permissions. Remove them first so a -# subsequent execution test works. -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { (ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi - -{ echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6; } -if test -z "$ac_file"; then - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext - -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -{ echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } -{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6; } - -{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_compiler_gnu=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } -GCC=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - CFLAGS="" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cc_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 -echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cc_c89=$ac_arg -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6; } ;; - xno) - { echo "$as_me:$LINENO: result: unsupported" >&5 -echo "${ECHO_T}unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; -esac - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP -else - ac_cv_prog_CPP=$CPP -fi -{ echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6; } -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - done - done - ;; -esac -done -IFS=$as_save_IFS - - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - - -if test "x${cache_file}" = "x/dev/null"; then - # Likewise, ensure that CC and CPP are passed through to the pcre - # configure script iff caching is disabled (the autoconf 2.5x default). - export CC; export CPP -fi - -echo $ac_n "Configuring Serf...${nl}" - -abs_srcdir=`(cd $srcdir && pwd)` -abs_builddir=`pwd` - -get_version="$abs_srcdir/build/get-version.sh" -version_hdr="$abs_srcdir/serf.h" -SERF_MAJOR_VERSION="`$get_version major $version_hdr SERF`" -SERF_DOTTED_VERSION="`$get_version all $version_hdr SERF`" - - - - - - - - -# Check whether --with-openssl was given. -if test "${with_openssl+set}" = set; then - withval=$with_openssl; - if test "$withval" = "yes"; then - { { echo "$as_me:$LINENO: error: --with-openssl requires a path" >&5 -echo "$as_me: error: --with-openssl requires a path" >&2;} - { (exit 1); exit 1; }; } - else - openssl_prefix=$withval - - if test "x$openssl_prefix" != "x" -a ! -d "$openssl_prefix"; then - { { echo "$as_me:$LINENO: error: '--with-openssl requires a path to a directory'" >&5 -echo "$as_me: error: '--with-openssl requires a path to a directory'" >&2;} - { (exit 1); exit 1; }; } - fi - - - if test "x$CPPFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting CPPFLAGS to \""-I${openssl_prefix}/include"\"" - CPPFLAGS=""-I${openssl_prefix}/include"" - else - apr_addto_bugger=""-I${openssl_prefix}/include"" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $CPPFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to CPPFLAGS" - CPPFLAGS="$CPPFLAGS $i" - fi - done - fi - - if test -e "${openssl_prefix}/Makefile"; then - - if test "x$LDFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting LDFLAGS to \""-L${openssl_prefix}"\"" - LDFLAGS=""-L${openssl_prefix}"" - else - apr_addto_bugger=""-L${openssl_prefix}"" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $LDFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" - LDFLAGS="$LDFLAGS $i" - fi - done - fi - - - if test "x$LDFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting LDFLAGS to \""-R${openssl_prefix}"\"" - LDFLAGS=""-R${openssl_prefix}"" - else - apr_addto_bugger=""-R${openssl_prefix}"" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $LDFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" - LDFLAGS="$LDFLAGS $i" - fi - done - fi - - else - - if test "x$LDFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting LDFLAGS to \""-L${openssl_prefix}/lib"\"" - LDFLAGS=""-L${openssl_prefix}/lib"" - else - apr_addto_bugger=""-L${openssl_prefix}/lib"" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $LDFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" - LDFLAGS="$LDFLAGS $i" - fi - done - fi - - - if test "x$LDFLAGS" = "x"; then - test "x$silent" != "xyes" && echo " setting LDFLAGS to \""-R${openssl_prefix}/lib"\"" - LDFLAGS=""-R${openssl_prefix}/lib"" - else - apr_addto_bugger=""-R${openssl_prefix}/lib"" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $LDFLAGS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" - LDFLAGS="$LDFLAGS $i" - fi - done - fi - - fi - fi - -fi - - - - -{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 -echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } -if test "${ac_cv_path_GREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Extract the first word of "grep ggrep" to use in msg output -if test -z "$GREP"; then -set dummy grep ggrep; ac_prog_name=$2 -if test "${ac_cv_path_GREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_path_GREP_found=false -# Loop through the user's path and test for each of PROGNAME-LIST -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue - # Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - - $ac_path_GREP_found && break 3 - done -done - -done -IFS=$as_save_IFS - - -fi - -GREP="$ac_cv_path_GREP" -if test -z "$GREP"; then - { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } -fi - -else - ac_cv_path_GREP=$GREP -fi - - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 -echo "${ECHO_T}$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - # Extract the first word of "egrep" to use in msg output -if test -z "$EGREP"; then -set dummy egrep; ac_prog_name=$2 -if test "${ac_cv_path_EGREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_path_EGREP_found=false -# Loop through the user's path and test for each of PROGNAME-LIST -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue - # Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - - $ac_path_EGREP_found && break 3 - done -done - -done -IFS=$as_save_IFS - - -fi - -EGREP="$ac_cv_path_EGREP" -if test -z "$EGREP"; then - { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } -fi - -else - ac_cv_path_EGREP=$EGREP -fi - - - fi -fi -{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 -echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_header_stdc=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f -r conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f -r conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - - -fi -fi -{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_Header=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -if test "${ac_cv_header_openssl_opensslv_h+set}" = set; then - { echo "$as_me:$LINENO: checking for openssl/opensslv.h" >&5 -echo $ECHO_N "checking for openssl/opensslv.h... $ECHO_C" >&6; } -if test "${ac_cv_header_openssl_opensslv_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_opensslv_h" >&5 -echo "${ECHO_T}$ac_cv_header_openssl_opensslv_h" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking openssl/opensslv.h usability" >&5 -echo $ECHO_N "checking openssl/opensslv.h usability... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking openssl/opensslv.h presence" >&5 -echo $ECHO_N "checking openssl/opensslv.h presence... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: openssl/opensslv.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: openssl/opensslv.h: in the future, the compiler will take precedence" >&2;} - - ;; -esac -{ echo "$as_me:$LINENO: checking for openssl/opensslv.h" >&5 -echo $ECHO_N "checking for openssl/opensslv.h... $ECHO_C" >&6; } -if test "${ac_cv_header_openssl_opensslv_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_openssl_opensslv_h=$ac_header_preproc -fi -{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_opensslv_h" >&5 -echo "${ECHO_T}$ac_cv_header_openssl_opensslv_h" >&6; } - -fi -if test $ac_cv_header_openssl_opensslv_h = yes; then - : -else - { { echo "$as_me:$LINENO: error: We require OpenSSL; try --with-openssl" >&5 -echo "$as_me: error: We require OpenSSL; try --with-openssl" >&2;} - { (exit 1); exit 1; }; } -fi - - - -{ echo "$as_me:$LINENO: checking for library containing fabs" >&5 -echo $ECHO_N "checking for library containing fabs... $ECHO_C" >&6; } -if test "${ac_cv_search_fabs+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_func_search_save_LIBS=$LIBS -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char fabs (); -int -main () -{ -return fabs (); - ; - return 0; -} -_ACEOF -for ac_lib in '' m; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - ac_cv_search_fabs=$ac_res -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext - if test "${ac_cv_search_fabs+set}" = set; then - break -fi -done -if test "${ac_cv_search_fabs+set}" = set; then - : -else - ac_cv_search_fabs=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ echo "$as_me:$LINENO: result: $ac_cv_search_fabs" >&5 -echo "${ECHO_T}$ac_cv_search_fabs" >&6; } -ac_res=$ac_cv_search_fabs -if test "$ac_res" != no; then - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -fi - - -libs="" -if test -n "$apu_config"; then - - if test "x$libs" = "x"; then - test "x$silent" != "xyes" && echo " setting libs to \"`$apu_config --link-libtool --libs`\"" - libs="`$apu_config --link-libtool --libs`" - else - apr_addto_bugger="`$apu_config --link-libtool --libs`" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $libs; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to libs" - libs="$libs $i" - fi - done - fi - -fi - - if test "x$libs" = "x"; then - test "x$silent" != "xyes" && echo " setting libs to \"`$apr_config --link-libtool --libs` $LIBS\"" - libs="`$apr_config --link-libtool --libs` $LIBS" - else - apr_addto_bugger="`$apr_config --link-libtool --libs` $LIBS" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $libs; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to libs" - libs="$libs $i" - fi - done - fi - - - - if test "x$SERF_LIBS" = "x"; then - test "x$silent" != "xyes" && echo " setting SERF_LIBS to \"$libs\"" - SERF_LIBS="$libs" - else - apr_addto_bugger="$libs" - for i in $apr_addto_bugger; do - apr_addto_duplicate="0" - for j in $SERF_LIBS; do - if test "x$i" = "x$j"; then - apr_addto_duplicate="1" - break - fi - done - if test $apr_addto_duplicate = "0"; then - test "x$silent" != "xyes" && echo " adding \"$i\" to SERF_LIBS" - SERF_LIBS="$SERF_LIBS $i" - fi - done - fi - - - - -set X $apr_ste_save_CPPFLAGS -if test ${#} -eq 1; then - EXTRA_CPPFLAGS="$CPPFLAGS" - CPPFLAGS= -else - if test "x$apr_ste_save_CPPFLAGS" = "x$CPPFLAGS"; then - EXTRA_CPPFLAGS= - else - EXTRA_CPPFLAGS=`echo "$CPPFLAGS" | sed -e "s%${apr_ste_save_CPPFLAGS}%%"` - CPPFLAGS="$apr_ste_save_CPPFLAGS" - fi -fi -if test "x$silent" != "xyes"; then - echo " restoring CPPFLAGS to \"$CPPFLAGS\"" - echo " setting EXTRA_CPPFLAGS to \"$EXTRA_CPPFLAGS\"" -fi - - - -set X $apr_ste_save_CFLAGS -if test ${#} -eq 1; then - EXTRA_CFLAGS="$CFLAGS" - CFLAGS= -else - if test "x$apr_ste_save_CFLAGS" = "x$CFLAGS"; then - EXTRA_CFLAGS= - else - EXTRA_CFLAGS=`echo "$CFLAGS" | sed -e "s%${apr_ste_save_CFLAGS}%%"` - CFLAGS="$apr_ste_save_CFLAGS" - fi -fi -if test "x$silent" != "xyes"; then - echo " restoring CFLAGS to \"$CFLAGS\"" - echo " setting EXTRA_CFLAGS to \"$EXTRA_CFLAGS\"" -fi - - - -set X $apr_ste_save_CXXFLAGS -if test ${#} -eq 1; then - EXTRA_CXXFLAGS="$CXXFLAGS" - CXXFLAGS= -else - if test "x$apr_ste_save_CXXFLAGS" = "x$CXXFLAGS"; then - EXTRA_CXXFLAGS= - else - EXTRA_CXXFLAGS=`echo "$CXXFLAGS" | sed -e "s%${apr_ste_save_CXXFLAGS}%%"` - CXXFLAGS="$apr_ste_save_CXXFLAGS" - fi -fi -if test "x$silent" != "xyes"; then - echo " restoring CXXFLAGS to \"$CXXFLAGS\"" - echo " setting EXTRA_CXXFLAGS to \"$EXTRA_CXXFLAGS\"" -fi - - - -set X $apr_ste_save_LDFLAGS -if test ${#} -eq 1; then - EXTRA_LDFLAGS="$LDFLAGS" - LDFLAGS= -else - if test "x$apr_ste_save_LDFLAGS" = "x$LDFLAGS"; then - EXTRA_LDFLAGS= - else - EXTRA_LDFLAGS=`echo "$LDFLAGS" | sed -e "s%${apr_ste_save_LDFLAGS}%%"` - LDFLAGS="$apr_ste_save_LDFLAGS" - fi -fi -if test "x$silent" != "xyes"; then - echo " restoring LDFLAGS to \"$LDFLAGS\"" - echo " setting EXTRA_LDFLAGS to \"$EXTRA_LDFLAGS\"" -fi - - - -set X $apr_ste_save_LIBS -if test ${#} -eq 1; then - EXTRA_LIBS="$LIBS" - LIBS= -else - if test "x$apr_ste_save_LIBS" = "x$LIBS"; then - EXTRA_LIBS= - else - EXTRA_LIBS=`echo "$LIBS" | sed -e "s%${apr_ste_save_LIBS}%%"` - LIBS="$apr_ste_save_LIBS" - fi -fi -if test "x$silent" != "xyes"; then - echo " restoring LIBS to \"$LIBS\"" - echo " setting EXTRA_LIBS to \"$EXTRA_LIBS\"" -fi - - - -set X $apr_ste_save_INCLUDES -if test ${#} -eq 1; then - EXTRA_INCLUDES="$INCLUDES" - INCLUDES= -else - if test "x$apr_ste_save_INCLUDES" = "x$INCLUDES"; then - EXTRA_INCLUDES= - else - EXTRA_INCLUDES=`echo "$INCLUDES" | sed -e "s%${apr_ste_save_INCLUDES}%%"` - INCLUDES="$apr_ste_save_INCLUDES" - fi -fi -if test "x$silent" != "xyes"; then - echo " restoring INCLUDES to \"$INCLUDES\"" - echo " setting EXTRA_INCLUDES to \"$EXTRA_INCLUDES\"" -fi - - - -ac_config_files="$ac_config_files Makefile serf.pc" - -ac_config_commands="$ac_config_commands mkdir-vpath" - - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { echo "$as_me:$LINENO: updating cache $cache_file" >&5 -echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file - else - { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 -echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -as_nl=' -' -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } -fi - -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# CDPATH. -$as_unset CDPATH - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in --n*) - case `echo 'x\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; - esac;; -*) - ECHO_N='-n';; -esac - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir -fi -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 - -# Save the log message, to keep $[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by $as_me, which was -generated by GNU Autoconf 2.61. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -# Files that config.status was made for. -config_files="$ac_config_files" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Configuration commands: -$config_commands - -Report bugs to ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -config.status -configured by $0, generated by GNU Autoconf 2.61, - with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" - -Copyright (C) 2006 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - echo "$ac_cs_version"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - CONFIG_SHELL=$SHELL - export CONFIG_SHELL - exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "serf.pc") CONFIG_FILES="$CONFIG_FILES serf.pc" ;; - "mkdir-vpath") CONFIG_COMMANDS="$CONFIG_COMMANDS mkdir-vpath" ;; - - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= - trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status -' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -# -# Set up the sed scripts for CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "$CONFIG_FILES"; then - -_ACEOF - - - -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - cat >conf$$subs.sed <<_ACEOF -SHELL!$SHELL$ac_delim -PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim -PACKAGE_NAME!$PACKAGE_NAME$ac_delim -PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim -PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim -PACKAGE_STRING!$PACKAGE_STRING$ac_delim -PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim -exec_prefix!$exec_prefix$ac_delim -prefix!$prefix$ac_delim -program_transform_name!$program_transform_name$ac_delim -bindir!$bindir$ac_delim -sbindir!$sbindir$ac_delim -libexecdir!$libexecdir$ac_delim -datarootdir!$datarootdir$ac_delim -datadir!$datadir$ac_delim -sysconfdir!$sysconfdir$ac_delim -sharedstatedir!$sharedstatedir$ac_delim -localstatedir!$localstatedir$ac_delim -includedir!$includedir$ac_delim -oldincludedir!$oldincludedir$ac_delim -docdir!$docdir$ac_delim -infodir!$infodir$ac_delim -htmldir!$htmldir$ac_delim -dvidir!$dvidir$ac_delim -pdfdir!$pdfdir$ac_delim -psdir!$psdir$ac_delim -libdir!$libdir$ac_delim -localedir!$localedir$ac_delim -mandir!$mandir$ac_delim -DEFS!$DEFS$ac_delim -ECHO_C!$ECHO_C$ac_delim -ECHO_N!$ECHO_N$ac_delim -ECHO_T!$ECHO_T$ac_delim -LIBS!$LIBS$ac_delim -build_alias!$build_alias$ac_delim -host_alias!$host_alias$ac_delim -target_alias!$target_alias$ac_delim -mkdir_p!$mkdir_p$ac_delim -build!$build$ac_delim -build_cpu!$build_cpu$ac_delim -build_vendor!$build_vendor$ac_delim -build_os!$build_os$ac_delim -host!$host$ac_delim -host_cpu!$host_cpu$ac_delim -host_vendor!$host_vendor$ac_delim -host_os!$host_os$ac_delim -target!$target$ac_delim -target_cpu!$target_cpu$ac_delim -target_vendor!$target_vendor$ac_delim -target_os!$target_os$ac_delim -LTFLAGS!$LTFLAGS$ac_delim -APR_LIBTOOL!$APR_LIBTOOL$ac_delim -APR_BINDIR!$APR_BINDIR$ac_delim -APR_INCLUDES!$APR_INCLUDES$ac_delim -APR_VERSION!$APR_VERSION$ac_delim -APR_CONFIG!$APR_CONFIG$ac_delim -APU_BINDIR!$APU_BINDIR$ac_delim -APU_INCLUDES!$APU_INCLUDES$ac_delim -APU_VERSION!$APU_VERSION$ac_delim -APU_CONFIG!$APU_CONFIG$ac_delim -CC!$CC$ac_delim -CFLAGS!$CFLAGS$ac_delim -LDFLAGS!$LDFLAGS$ac_delim -CPPFLAGS!$CPPFLAGS$ac_delim -ac_ct_CC!$ac_ct_CC$ac_delim -EXEEXT!$EXEEXT$ac_delim -OBJEXT!$OBJEXT$ac_delim -CPP!$CPP$ac_delim -INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim -INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim -INSTALL_DATA!$INSTALL_DATA$ac_delim -SERF_MAJOR_VERSION!$SERF_MAJOR_VERSION$ac_delim -SERF_DOTTED_VERSION!$SERF_DOTTED_VERSION$ac_delim -SERF_BUILD_SRCLIB_DIRS!$SERF_BUILD_SRCLIB_DIRS$ac_delim -SERF_CLEAN_SRCLIB_DIRS!$SERF_CLEAN_SRCLIB_DIRS$ac_delim -GREP!$GREP$ac_delim -EGREP!$EGREP$ac_delim -SERF_LIBS!$SERF_LIBS$ac_delim -EXTRA_CPPFLAGS!$EXTRA_CPPFLAGS$ac_delim -EXTRA_CFLAGS!$EXTRA_CFLAGS$ac_delim -EXTRA_CXXFLAGS!$EXTRA_CXXFLAGS$ac_delim -EXTRA_LDFLAGS!$EXTRA_LDFLAGS$ac_delim -EXTRA_LIBS!$EXTRA_LIBS$ac_delim -EXTRA_INCLUDES!$EXTRA_INCLUDES$ac_delim -LIBOBJS!$LIBOBJS$ac_delim -LTLIBOBJS!$LTLIBOBJS$ac_delim -_ACEOF - - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 86; then - break - elif $ac_last_try; then - { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done - -ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` -if test -n "$ac_eof"; then - ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` - ac_eof=`expr $ac_eof + 1` -fi - -cat >>$CONFIG_STATUS <<_ACEOF -cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end -_ACEOF -sed ' -s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g -s/^/s,@/; s/!/@,|#_!!_#|/ -:n -t n -s/'"$ac_delim"'$/,g/; t -s/$/\\/; p -N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n -' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF -:end -s/|#_!!_#|//g -CEOF$ac_eof -_ACEOF - - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ -s/:*$// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF -fi # test -n "$CONFIG_FILES" - - -for ac_tag in :F $CONFIG_FILES :C $CONFIG_COMMANDS -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 -echo "$as_me: error: Invalid tag $ac_tag." >&2;} - { (exit 1); exit 1; }; };; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 -echo "$as_me: error: cannot find input file: $ac_f" >&2;} - { (exit 1); exit 1; }; };; - esac - ac_file_inputs="$ac_file_inputs $ac_f" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input="Generated from "`IFS=: - echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - fi - - case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin";; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - { as_dir="$ac_dir" - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 -echo "$as_me: error: cannot create directory $as_dir" >&2;} - { (exit 1); exit 1; }; }; } - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= - -case `sed -n '/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p -' $ac_file_inputs` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s&@configure_input@&$configure_input&;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -$ac_datarootdir_hack -" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && - { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 -echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} - - rm -f "$tmp/stdin" - case $ac_file in - -) cat "$tmp/out"; rm -f "$tmp/out";; - *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; - esac - ;; - - - :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 -echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "mkdir-vpath":C) make mkdir-vpath ;; - - esac -done # for ac_tag - - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - diff -Nru serf-1.1.0/configure.in serf-1.3.3/configure.in --- serf-1.1.0/configure.in 2011-07-13 01:10:50.000000000 +0000 +++ serf-1.3.3/configure.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,219 +0,0 @@ -dnl Autoconf file for Serf - -AC_PREREQ(2.50) -AC_INIT(context.c) - -AC_CONFIG_AUX_DIR(build) - -sinclude(build/apr_common.m4) -sinclude(build/find_apr.m4) - -AC_PREFIX_DEFAULT(/usr/local/serf) - -dnl Get the layout here, so we can pass the required variables to apr -APR_ENABLE_LAYOUT(Serf, []) - -dnl reparse the configure arguments. -APR_PARSE_ARGUMENTS - -APR_SAVE_THE_ENVIRONMENT(CPPFLAGS) -APR_SAVE_THE_ENVIRONMENT(CFLAGS) -APR_SAVE_THE_ENVIRONMENT(CXXFLAGS) -APR_SAVE_THE_ENVIRONMENT(LDFLAGS) -APR_SAVE_THE_ENVIRONMENT(LIBS) -APR_SAVE_THE_ENVIRONMENT(INCLUDES) - -APR_CONFIG_NICE(config.nice) - -nl=' -' -dnl Check that mkdir -p works -APR_MKDIR_P_CHECK($top_srcdir/build/mkdir.sh) -AC_SUBST(mkdir_p) - -dnl ## Run configure for packages Apache uses - -dnl shared library support for these packages doesn't currently -dnl work on some platforms - -AC_CANONICAL_SYSTEM - -orig_prefix="$prefix" - -echo $ac_n "${nl}Configuring Apache Portable Runtime library...${nl}" - -APR_FIND_APR("$srcdir/apr", "./apr", 1, 0 1 2) - -if test "$apr_found" = "no"; then - AC_MSG_ERROR([APR not found. Please read the documentation.]) -fi - -if test "$apr_found" = "reconfig"; then - APR_SUBDIR_CONFIG(apr, - [--prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir --datadir=$datadir --with-installbuilddir=$installbuilddir], - [--enable-layout=*|\'--enable-layout=*]) - dnl We must be the first to build and the last to be cleaned - SERF_BUILD_SRCLIB_DIRS="apr $SERF_BUILD_SRCLIB_DIRS" - SERF_CLEAN_SRCLIB_DIRS="$SERF_CLEAN_SRCLIB_DIRS apr" -fi - -APR_SETIFNULL(CC, `$apr_config --cc`) -APR_SETIFNULL(CPP, `$apr_config --cpp`) -APR_SETIFNULL(APR_LIBTOOL, `$apr_config --apr-libtool`) -APR_ADDTO(CFLAGS, `$apr_config --cflags`) -APR_ADDTO(CPPFLAGS, `$apr_config --cppflags`) -APR_ADDTO(LDFLAGS, `$apr_config --ldflags`) -SHLIBPATH_VAR=`$apr_config --shlib-path-var` -APR_BINDIR=`$apr_config --bindir` -APR_INCLUDES=`$apr_config --includes` -APR_VERSION=`$apr_config --version` -APR_CONFIG="$apr_config" - -APR_SETIFNULL(LTFLAGS, "--silent") -AC_SUBST(LTFLAGS) - -AC_SUBST(APR_LIBTOOL) -AC_SUBST(APR_BINDIR) -AC_SUBST(APR_INCLUDES) -AC_SUBST(APR_VERSION) -AC_SUBST(APR_CONFIG) - -APR_VERSION_MAJOR="`echo \"$APR_VERSION\" | sed 's,\..*,,'`" -APR_VERSION_NUM="`echo \"$APR_VERSION\" | \ - sed -e 's/[[^0-9\.]].*$//' \ - -e 's/\.\([[0-9]]\)$/.0\1/' \ - -e 's/\.\([[0-9]][[0-9]]\)$/.0\1/' \ - -e 's/\.\([[0-9]]\)\./0\1/; s/\.//g;'`" - -if test "$APR_VERSION_NUM" -ge "200000"; then - - APU_BINDIR="" - APU_INCLUDES="" - APU_VERSION="" - APU_CONFIG="" - -else - sinclude(build/find_apu.m4) - - echo $ac_n "${nl}Configuring Apache Portable Runtime Utility library...${nl}" - - ifdef([APR_FIND_APU], [ - APR_FIND_APU("$srcdir/apr-util", "./apr-util", 1, $APR_VERSION_MAJOR) - ], [AC_MSG_ERROR([APR-util required, but find_apu.m4 not present!])]) - - if test "$apu_found" = "no"; then - AC_MSG_ERROR([APR-util not found. Please read the documentation.]) - fi - - # Catch some misconfigurations: - case ${apr_found}.${apu_found} in - reconfig.yes) - AC_MSG_ERROR([Cannot use an external APR-util with the bundled APR]) - ;; - yes.reconfig) - AC_MSG_ERROR([Cannot use an external APR with the bundled APR-util]) - ;; - esac - - if test "$apu_found" = "reconfig"; then - APR_SUBDIR_CONFIG(apr-util, - [--with-apr=../apr --prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir], - [--enable-layout=*|\'--enable-layout=*]) - dnl We must be the last to build and the first to be cleaned - SERF_BUILD_SRCLIB_DIRS="$SERF_BUILD_SRCLIB_DIRS apr-util" - SERF_CLEAN_SRCLIB_DIRS="apr-util $SERF_CLEAN_SRCLIB_DIRS" - fi - - APR_ADDTO(LDFLAGS, `$apu_config --ldflags`) - APU_BINDIR=`$apu_config --bindir` - APU_INCLUDES=`$apu_config --includes` - APU_VERSION=`$apu_config --version` - APU_CONFIG="$APU_BINDIR/apu-`echo ${APU_VERSION} | sed 's,\..*,,'`-config" -fi - -AC_SUBST(APU_BINDIR) -AC_SUBST(APU_INCLUDES) -AC_SUBST(APU_VERSION) -AC_SUBST(APU_CONFIG) - -dnl In case we picked up CC and CPP from APR, get that info into the -dnl config cache so that PCRE uses it. Otherwise, CC and CPP used for -dnl PCRE and for our config tests will be whatever PCRE determines. -AC_PROG_CC -AC_PROG_CPP -AC_PROG_INSTALL - -if test "x${cache_file}" = "x/dev/null"; then - # Likewise, ensure that CC and CPP are passed through to the pcre - # configure script iff caching is disabled (the autoconf 2.5x default). - export CC; export CPP -fi - -echo $ac_n "Configuring Serf...${nl}" - -dnl Absolute source/build directory -abs_srcdir=`(cd $srcdir && pwd)` -abs_builddir=`pwd` - -dnl get our version information -get_version="$abs_srcdir/build/get-version.sh" -version_hdr="$abs_srcdir/serf.h" -SERF_MAJOR_VERSION="`$get_version major $version_hdr SERF`" -SERF_DOTTED_VERSION="`$get_version all $version_hdr SERF`" - -AC_SUBST(SERF_MAJOR_VERSION) -AC_SUBST(SERF_DOTTED_VERSION) - -AC_SUBST(SERF_BUILD_SRCLIB_DIRS) -AC_SUBST(SERF_CLEAN_SRCLIB_DIRS) - -AC_ARG_WITH(openssl, - APR_HELP_STRING([--with-openssl=PATH],[Path to OpenSSL (eg. /usr/local/ssl)]), -[ - if test "$withval" = "yes"; then - AC_MSG_ERROR([--with-openssl requires a path]) - else - openssl_prefix=$withval - - if test "x$openssl_prefix" != "x" -a ! -d "$openssl_prefix"; then - AC_MSG_ERROR('--with-openssl requires a path to a directory') - fi - - APR_ADDTO(CPPFLAGS, "-I${openssl_prefix}/include") - if test -e "${openssl_prefix}/Makefile"; then - APR_ADDTO(LDFLAGS, "-L${openssl_prefix}") - APR_ADDTO(LDFLAGS, "-R${openssl_prefix}") - else - APR_ADDTO(LDFLAGS, "-L${openssl_prefix}/lib") - APR_ADDTO(LDFLAGS, "-R${openssl_prefix}/lib") - fi - fi -]) - -dnl Look for OpenSSL -AC_CHECK_HEADER([openssl/opensslv.h], [], - [AC_MSG_ERROR([We require OpenSSL; try --with-openssl])]) - -dnl CuTest requires libm on Solaris -AC_SEARCH_LIBS(fabs, m) - -libs="" -if test -n "$apu_config"; then - APR_ADDTO(libs, [`$apu_config --link-libtool --libs`]) -fi -APR_ADDTO(libs, [`$apr_config --link-libtool --libs` $LIBS]) - -APR_ADDTO(SERF_LIBS, [$libs]) -AC_SUBST(SERF_LIBS) - -APR_RESTORE_THE_ENVIRONMENT(CPPFLAGS, EXTRA_) -APR_RESTORE_THE_ENVIRONMENT(CFLAGS, EXTRA_) -APR_RESTORE_THE_ENVIRONMENT(CXXFLAGS, EXTRA_) -APR_RESTORE_THE_ENVIRONMENT(LDFLAGS, EXTRA_) -APR_RESTORE_THE_ENVIRONMENT(LIBS, EXTRA_) -APR_RESTORE_THE_ENVIRONMENT(INCLUDES, EXTRA_) - -AC_CONFIG_FILES([Makefile serf.pc]) -AC_CONFIG_COMMANDS([mkdir-vpath],[make mkdir-vpath]) - -AC_OUTPUT diff -Nru serf-1.1.0/context.c serf-1.3.3/context.c --- serf-1.1.0/context.c 2011-07-13 02:39:16.000000000 +0000 +++ serf-1.3.3/context.c 2013-11-29 21:57:23.000000000 +0000 @@ -22,20 +22,6 @@ #include "serf_private.h" -/* Older versions of APR do not have the APR_VERSION_AT_LEAST macro. Those - implementations are safe. - - If the macro *is* defined, and we're on WIN32, and APR is version 1.4.0, - then we have a broken WSAPoll() implementation. - - See serf_context_create_ex() below. */ -#if defined(APR_VERSION_AT_LEAST) && defined(WIN32) -#if APR_VERSION_AT_LEAST(1,4,0) -#define BROKEN_WSAPOLL -#endif -#endif - - /** * Callback function (implements serf_progress_t). Takes a number of bytes * read @a read and bytes written @a written, adds those to the total for this @@ -149,6 +135,12 @@ else { /* build the pollset with a (default) number of connections */ serf_pollset_t *ps = apr_pcalloc(pool, sizeof(*ps)); + + /* ### TODO: As of APR 1.4.x apr_pollset_create_ex can return a status + ### other than APR_SUCCESS, so we should handle it. + ### Probably move creation of the pollset to later when we have + ### the possibility of returning status to the caller. + */ #ifdef BROKEN_WSAPOLL /* APR 1.4.x switched to using WSAPoll() on Win32, but it does not * properly handle errors on a non-blocking sockets (such as @@ -176,6 +168,7 @@ ctx->progress_written = 0; ctx->authn_types = SERF_AUTHN_ALL; + ctx->server_authn_info = apr_hash_make(pool); return ctx; } @@ -283,10 +276,21 @@ if ((status = apr_pollset_poll(ps->pollset, duration, &num, &desc)) != APR_SUCCESS) { + /* EINTR indicates a handled signal happened during the poll call, + ignore, the application can safely retry. */ + if (APR_STATUS_IS_EINTR(status)) + return APR_SUCCESS; + /* ### do we still need to dispatch stuff here? ### look at the potential return codes. map to our defined ### return values? ... */ + + /* Use the strict documented error for poll timeouts, to allow proper + handling of the other timeout types when returned from + serf_event_trigger */ + if (APR_STATUS_IS_TIMEUP(status)) + return APR_TIMEUP; /* Return the documented error */ return status; } @@ -354,6 +358,14 @@ return "An error occurred during decompression"; case SERF_ERROR_BAD_HTTP_RESPONSE: return "The server sent an improper HTTP response"; + case SERF_ERROR_TRUNCATED_HTTP_RESPONSE: + return "The server sent a truncated HTTP response body."; + case SERF_ERROR_ABORTED_CONNECTION: + return "The server unexpectedly closed the connection."; + case SERF_ERROR_SSL_COMM_FAILED: + return "An error occurred during SSL communication"; + case SERF_ERROR_SSL_CERT_FAILED: + return "An SSL certificate related error occurred "; case SERF_ERROR_AUTHN_FAILED: return "An error occurred during authentication"; case SERF_ERROR_AUTHN_NOT_SUPPORTED: @@ -362,7 +374,9 @@ return "An authentication attribute is missing"; case SERF_ERROR_AUTHN_INITALIZATION_FAILED: return "Initialization of an authentication type failed"; - + case SERF_ERROR_SSLTUNNEL_SETUP_FAILED: + return "The proxy server returned an error while setting up the " + "SSL tunnel."; default: return NULL; } diff -Nru serf-1.1.0/debian/changelog serf-1.3.3/debian/changelog --- serf-1.1.0/debian/changelog 2014-01-07 01:18:14.000000000 +0000 +++ serf-1.3.3/debian/changelog 2014-01-07 01:18:14.000000000 +0000 @@ -1,8 +1,19 @@ -serf (1.1.0-2ubuntu1) saucy; urgency=low +serf (1.3.3-1) unstable; urgency=low - * Copy config.{guess,sub} into the correct directory. + * Add myself to Uploaders. + * Change the watch file to better handle code.google.com. + * New upstream release. (Closes: #716793) + + Refresh patches/libtool + + Update symbols + * Adapt packaging for the upstream switch to SCons. + + control: + scons, - autotools-dev, autoconf + + rules: Change configure/make calls to scons + * Rename libserf1 to libserf-1-1, following standard naming conventions. + * Enable hardening flags. + * Strip unnecessary RPATH from libserf. + * Honor DEB_BUILD_OPTIONS=parallel=X - -- Matthias Klose Wed, 09 Oct 2013 11:39:24 +0200 + -- James McCoy Tue, 31 Dec 2013 13:17:16 -0500 serf (1.1.0-2) unstable; urgency=low diff -Nru serf-1.1.0/debian/control serf-1.3.3/debian/control --- serf-1.1.0/debian/control 2014-01-07 01:18:14.000000000 +0000 +++ serf-1.3.3/debian/control 2014-01-07 01:18:14.000000000 +0000 @@ -2,12 +2,13 @@ Section: libs Priority: optional Maintainer: Peter Samuelson -Build-Depends: dpkg-dev (>= 1.16.0~), debhelper, - quilt, autoconf, autotools-dev, libapr1-dev, libaprutil1-dev +Uploaders: James McCoy +Build-Depends: dpkg-dev (>= 1.16.0~), debhelper, scons (>= 2.3.0), + quilt, libapr1-dev, libaprutil1-dev, chrpath Standards-Version: 3.9.3 Homepage: http://code.google.com/p/serf/ -Package: libserf1 +Package: libserf-1-1 Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} @@ -23,10 +24,7 @@ Package: libserf-dev Section: libdevel Architecture: any -Depends: libserf1 (= ${binary:Version}), ${misc:Depends}, libapr1-dev, libaprutil1-dev -Replaces: libserf-0-0 (<< 0.3.0-1), libserf-0-0-dev -Conflicts: libserf-0-0-dev -Provides: libserf-0-0-dev +Depends: libserf-1-1 (= ${binary:Version}), ${misc:Depends}, libapr1-dev, libaprutil1-dev Description: high-performance asynchronous HTTP client library headers serf library is a C-based HTTP client library built upon the Apache Portable Runtime (APR) library. It multiplexes connections, running the @@ -41,7 +39,7 @@ Priority: extra Architecture: any Multi-Arch: same -Depends: libserf1 (= ${binary:Version}), ${misc:Depends} +Depends: libserf-1-1 (= ${binary:Version}), ${misc:Depends} Provides: libserf-dbg Description: high-performance asynchronous HTTP client library debugging symbols serf library is a C-based HTTP client library built upon the Apache diff -Nru serf-1.1.0/debian/libserf-1-1.lintian-overrides serf-1.3.3/debian/libserf-1-1.lintian-overrides --- serf-1.1.0/debian/libserf-1-1.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/debian/libserf-1-1.lintian-overrides 2014-01-07 01:18:14.000000000 +0000 @@ -0,0 +1,2 @@ +# This one is intentional +symbols-declares-dependency-on-other-package libserf-private diff -Nru serf-1.1.0/debian/libserf-1-1.symbols serf-1.3.3/debian/libserf-1-1.symbols --- serf-1.1.0/debian/libserf-1-1.symbols 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/debian/libserf-1-1.symbols 2014-01-07 01:18:14.000000000 +0000 @@ -0,0 +1,143 @@ +libserf-1.so.1 libserf-1-1 #MINVER# +| libserf-private +* Build-Depends-Package: libserf-dev + (regex)__ 0 1 + serf_bmemdup@Base 1.0 + serf_bstrcatv@Base 1.3 + serf_bstrdup@Base 1.0 + serf_bstrmemdup@Base 1.0 + serf_bucket_aggregate_append@Base 1.0 + serf_bucket_aggregate_append_iovec@Base 1.0 + serf_bucket_aggregate_become@Base 1.0 + serf_bucket_aggregate_cleanup@Base 1.0 + serf_bucket_aggregate_create@Base 1.0 + serf_bucket_aggregate_hold_open@Base 1.0 + serf_bucket_aggregate_prepend@Base 1.0 + serf_bucket_aggregate_prepend_iovec@Base 1.0 + serf_bucket_allocator_create@Base 1.0 + serf_bucket_allocator_get_pool@Base 1.0 + serf_bucket_barrier_create@Base 1.0 + serf_bucket_bwtp_channel_close@Base 1.0 + serf_bucket_bwtp_channel_open@Base 1.0 + serf_bucket_bwtp_frame_get_channel@Base 1.0 + serf_bucket_bwtp_frame_get_headers@Base 1.0 + serf_bucket_bwtp_frame_get_phrase@Base 1.0 + serf_bucket_bwtp_frame_get_type@Base 1.0 + serf_bucket_bwtp_header_create@Base 1.0 + serf_bucket_bwtp_incoming_frame_create@Base 1.0 + serf_bucket_bwtp_incoming_frame_wait_for_headers@Base 1.0 + serf_bucket_bwtp_message_create@Base 1.0 + serf_bucket_chunk_create@Base 1.0 + serf_bucket_create@Base 1.0 + serf_bucket_dechunk_create@Base 1.0 + serf_bucket_deflate_create@Base 1.0 + serf_bucket_file_create@Base 1.0 + serf_bucket_headers_create@Base 1.0 + serf_bucket_headers_do@Base 1.0 + serf_bucket_headers_get@Base 1.0 + serf_bucket_headers_set@Base 1.0 + serf_bucket_headers_setc@Base 1.0 + serf_bucket_headers_setn@Base 1.0 + serf_bucket_headers_setx@Base 1.0 + serf_bucket_iovec_create@Base 1.0 + serf_bucket_limit_create@Base 1.0 + serf_bucket_mem_alloc@Base 1.0 + serf_bucket_mem_calloc@Base 1.0 + serf_bucket_mem_free@Base 1.0 + serf_bucket_mmap_create@Base 1.0 + serf_bucket_request_become@Base 1.0 + serf_bucket_request_create@Base 1.0 + serf_bucket_request_get_headers@Base 1.0 + serf_bucket_request_set_CL@Base 1.1 + serf_bucket_request_set_root@Base 1.0 + serf_bucket_response_body_create@Base 1.2 + serf_bucket_response_create@Base 1.0 + serf_bucket_response_get_headers@Base 1.0 + serf_bucket_response_set_head@Base 1.0 + serf_bucket_response_status@Base 1.0 + serf_bucket_response_wait_for_headers@Base 1.0 + serf_bucket_simple_copy_create@Base 1.0 + serf_bucket_simple_create@Base 1.0 + serf_bucket_simple_own_create@Base 1.3 + serf_bucket_socket_create@Base 1.0 + serf_bucket_socket_set_read_progress_cb@Base 1.0 + serf_bucket_ssl_decrypt_context_get@Base 1.0 + serf_bucket_ssl_decrypt_create@Base 1.0 + serf_bucket_ssl_encrypt_context_get@Base 1.0 + serf_bucket_ssl_encrypt_create@Base 1.0 + serf_bucket_type_aggregate@Base 1.0 + serf_bucket_type_barrier@Base 1.0 + serf_bucket_type_bwtp_frame@Base 1.0 + serf_bucket_type_bwtp_incoming_frame@Base 1.0 + serf_bucket_type_chunk@Base 1.0 + serf_bucket_type_dechunk@Base 1.0 + serf_bucket_type_deflate@Base 1.0 + serf_bucket_type_file@Base 1.0 + serf_bucket_type_headers@Base 1.0 + serf_bucket_type_iovec@Base 1.0 + serf_bucket_type_limit@Base 1.0 + serf_bucket_type_mmap@Base 1.0 + serf_bucket_type_request@Base 1.0 + serf_bucket_type_response@Base 1.0 + serf_bucket_type_response_body@Base 1.2 + serf_bucket_type_simple@Base 1.0 + serf_bucket_type_socket@Base 1.0 + serf_bucket_type_ssl_decrypt@Base 1.0 + serf_bucket_type_ssl_encrypt@Base 1.0 + serf_config_authn_types@Base 1.0 + serf_config_credentials_callback@Base 1.0 + serf_config_proxy@Base 1.0 + serf_connection_close@Base 1.0 + serf_connection_create2@Base 1.0 + serf_connection_create@Base 1.0 + serf_connection_get_latency@Base 1.2 + serf_connection_priority_request_create@Base 1.0 + serf_connection_request_create@Base 1.0 + serf_connection_reset@Base 1.0 + serf_connection_set_async_responses@Base 1.0 + serf_connection_set_max_outstanding_requests@Base 1.0 + serf_context_bucket_socket_create@Base 1.0 + serf_context_create@Base 1.0 + serf_context_create_ex@Base 1.0 + serf_context_prerun@Base 1.0 + serf_context_run@Base 1.0 + serf_context_set_progress_cb@Base 1.0 + serf_databuf_init@Base 1.0 + serf_databuf_peek@Base 1.0 + serf_databuf_read@Base 1.0 + serf_databuf_readline@Base 1.0 + serf_default_destroy@Base 1.0 + serf_default_destroy_and_data@Base 1.0 + serf_default_read_bucket@Base 1.0 + serf_default_read_for_sendfile@Base 1.0 + serf_default_read_iovec@Base 1.0 + serf_error_string@Base 1.0 + serf_event_trigger@Base 1.0 + serf_incoming_create@Base 1.0 + serf_lib_version@Base 1.0 + serf_linebuf_fetch@Base 1.0 + serf_linebuf_init@Base 1.0 + serf_listener_create@Base 1.0 + serf_request_bucket_request_create@Base 1.0 + serf_request_cancel@Base 1.0 + serf_request_get_alloc@Base 1.0 + serf_request_get_conn@Base 1.0 + serf_request_get_pool@Base 1.0 + serf_request_is_written@Base 1.2 + serf_request_set_handler@Base 1.0 + serf_response_full_become_aggregate@Base 1.2 + serf_ssl_cert_certificate@Base 1.0 + serf_ssl_cert_depth@Base 1.0 + serf_ssl_cert_export@Base 1.0 + serf_ssl_cert_issuer@Base 1.0 + serf_ssl_cert_subject@Base 1.0 + serf_ssl_client_cert_password_set@Base 1.0 + serf_ssl_client_cert_provider_set@Base 1.0 + serf_ssl_load_cert_file@Base 1.0 + serf_ssl_server_cert_callback_set@Base 1.0 + serf_ssl_server_cert_chain_callback_set@Base 1.1 + serf_ssl_set_hostname@Base 1.0 + serf_ssl_trust_cert@Base 1.0 + serf_ssl_use_compression@Base 1.2 + serf_ssl_use_default_certificates@Base 1.0 + serf_util_readline@Base 1.0 diff -Nru serf-1.1.0/debian/libserf1.lintian-overrides serf-1.3.3/debian/libserf1.lintian-overrides --- serf-1.1.0/debian/libserf1.lintian-overrides 2014-01-07 01:18:14.000000000 +0000 +++ serf-1.3.3/debian/libserf1.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -# This one is intentional -symbols-declares-dependency-on-other-package libserf-private -# This one is just silly -package-name-doesnt-match-sonames libserf-1-0 -# Pretty sure this is intentional upstream. Use 'pkgconfig --libs serf-1'. -dev-pkg-without-shlib-symlink usr/lib/*/libserf-1.so.* usr/lib/*/libserf.so diff -Nru serf-1.1.0/debian/libserf1.symbols serf-1.3.3/debian/libserf1.symbols --- serf-1.1.0/debian/libserf1.symbols 2014-01-07 01:18:14.000000000 +0000 +++ serf-1.3.3/debian/libserf1.symbols 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -libserf-1.so.0 libserf1 #MINVER# -| libserf-private -* Build-Depends-Package: libserf-dev - (regex)__ 0 1 - serf_bmemdup@Base 1.0 - serf_bstrdup@Base 1.0 - serf_bstrmemdup@Base 1.0 - serf_bucket_aggregate_append@Base 1.0 - serf_bucket_aggregate_append_iovec@Base 1.0 - serf_bucket_aggregate_become@Base 1.0 - serf_bucket_aggregate_cleanup@Base 1.0 - serf_bucket_aggregate_create@Base 1.0 - serf_bucket_aggregate_hold_open@Base 1.0 - serf_bucket_aggregate_prepend@Base 1.0 - serf_bucket_aggregate_prepend_iovec@Base 1.0 - serf_bucket_allocator_create@Base 1.0 - serf_bucket_allocator_get_pool@Base 1.0 - serf_bucket_barrier_create@Base 1.0 - serf_bucket_bwtp_channel_close@Base 1.0 - serf_bucket_bwtp_channel_open@Base 1.0 - serf_bucket_bwtp_frame_get_channel@Base 1.0 - serf_bucket_bwtp_frame_get_headers@Base 1.0 - serf_bucket_bwtp_frame_get_phrase@Base 1.0 - serf_bucket_bwtp_frame_get_type@Base 1.0 - serf_bucket_bwtp_header_create@Base 1.0 - serf_bucket_bwtp_incoming_frame_create@Base 1.0 - serf_bucket_bwtp_incoming_frame_wait_for_headers@Base 1.0 - serf_bucket_bwtp_message_create@Base 1.0 - serf_bucket_chunk_create@Base 1.0 - serf_bucket_create@Base 1.0 - serf_bucket_dechunk_create@Base 1.0 - serf_bucket_deflate_create@Base 1.0 - serf_bucket_file_create@Base 1.0 - serf_bucket_headers_create@Base 1.0 - serf_bucket_headers_do@Base 1.0 - serf_bucket_headers_get@Base 1.0 - serf_bucket_headers_set@Base 1.0 - serf_bucket_headers_setc@Base 1.0 - serf_bucket_headers_setn@Base 1.0 - serf_bucket_headers_setx@Base 1.0 - serf_bucket_iovec_create@Base 1.0 - serf_bucket_limit_create@Base 1.0 - serf_bucket_mem_alloc@Base 1.0 - serf_bucket_mem_calloc@Base 1.0 - serf_bucket_mem_free@Base 1.0 - serf_bucket_mmap_create@Base 1.0 - serf_bucket_request_become@Base 1.0 - serf_bucket_request_create@Base 1.0 - serf_bucket_request_get_headers@Base 1.0 - serf_bucket_request_set_CL@Base 1.1 - serf_bucket_request_set_root@Base 1.0 - serf_bucket_response_create@Base 1.0 - serf_bucket_response_get_headers@Base 1.0 - serf_bucket_response_set_head@Base 1.0 - serf_bucket_response_status@Base 1.0 - serf_bucket_response_wait_for_headers@Base 1.0 - serf_bucket_simple_copy_create@Base 1.0 - serf_bucket_simple_create@Base 1.0 - serf_bucket_socket_create@Base 1.0 - serf_bucket_socket_set_read_progress_cb@Base 1.0 - serf_bucket_ssl_decrypt_context_get@Base 1.0 - serf_bucket_ssl_decrypt_create@Base 1.0 - serf_bucket_ssl_encrypt_context_get@Base 1.0 - serf_bucket_ssl_encrypt_create@Base 1.0 - serf_bucket_type_aggregate@Base 1.0 - serf_bucket_type_barrier@Base 1.0 - serf_bucket_type_bwtp_frame@Base 1.0 - serf_bucket_type_bwtp_incoming_frame@Base 1.0 - serf_bucket_type_chunk@Base 1.0 - serf_bucket_type_dechunk@Base 1.0 - serf_bucket_type_deflate@Base 1.0 - serf_bucket_type_file@Base 1.0 - serf_bucket_type_headers@Base 1.0 - serf_bucket_type_iovec@Base 1.0 - serf_bucket_type_limit@Base 1.0 - serf_bucket_type_mmap@Base 1.0 - serf_bucket_type_request@Base 1.0 - serf_bucket_type_response@Base 1.0 - serf_bucket_type_simple@Base 1.0 - serf_bucket_type_socket@Base 1.0 - serf_bucket_type_ssl_decrypt@Base 1.0 - serf_bucket_type_ssl_encrypt@Base 1.0 - serf_config_authn_types@Base 1.0 - serf_config_credentials_callback@Base 1.0 - serf_config_proxy@Base 1.0 - serf_connection_close@Base 1.0 - serf_connection_create2@Base 1.0 - serf_connection_create@Base 1.0 - serf_connection_priority_request_create@Base 1.0 - serf_connection_request_create@Base 1.0 - serf_connection_reset@Base 1.0 - serf_connection_set_async_responses@Base 1.0 - serf_connection_set_max_outstanding_requests@Base 1.0 - serf_context_bucket_socket_create@Base 1.0 - serf_context_create@Base 1.0 - serf_context_create_ex@Base 1.0 - serf_context_prerun@Base 1.0 - serf_context_run@Base 1.0 - serf_context_set_progress_cb@Base 1.0 - serf_databuf_init@Base 1.0 - serf_databuf_peek@Base 1.0 - serf_databuf_read@Base 1.0 - serf_databuf_readline@Base 1.0 - serf_default_destroy@Base 1.0 - serf_default_destroy_and_data@Base 1.0 - serf_default_read_bucket@Base 1.0 - serf_default_read_for_sendfile@Base 1.0 - serf_default_read_iovec@Base 1.0 - serf_error_string@Base 1.0 - serf_event_trigger@Base 1.0 - serf_incoming_create@Base 1.0 - serf_lib_version@Base 1.0 - serf_linebuf_fetch@Base 1.0 - serf_linebuf_init@Base 1.0 - serf_listener_create@Base 1.0 - serf_request_bucket_request_create@Base 1.0 - serf_request_cancel@Base 1.0 - serf_request_get_alloc@Base 1.0 - serf_request_get_conn@Base 1.0 - serf_request_get_pool@Base 1.0 - serf_request_set_handler@Base 1.0 - serf_ssl_cert_certificate@Base 1.0 - serf_ssl_cert_depth@Base 1.0 - serf_ssl_cert_export@Base 1.0 - serf_ssl_cert_issuer@Base 1.0 - serf_ssl_cert_subject@Base 1.0 - serf_ssl_client_cert_password_set@Base 1.0 - serf_ssl_client_cert_provider_set@Base 1.0 - serf_ssl_load_cert_file@Base 1.0 - serf_ssl_server_cert_callback_set@Base 1.0 - serf_ssl_server_cert_chain_callback_set@Base 1.1 - serf_ssl_set_hostname@Base 1.0 - serf_ssl_trust_cert@Base 1.0 - serf_ssl_use_default_certificates@Base 1.0 - serf_util_readline@Base 1.0 diff -Nru serf-1.1.0/debian/patches/libtool serf-1.3.3/debian/patches/libtool --- serf-1.1.0/debian/patches/libtool 2014-01-07 01:18:14.000000000 +0000 +++ serf-1.3.3/debian/patches/libtool 2014-01-07 01:18:14.000000000 +0000 @@ -1,14 +1,13 @@ ---- a/configure.in -+++ b/configure.in -@@ -199,9 +199,9 @@ AC_SEARCH_LIBS(fabs, m) - - libs="" - if test -n "$apu_config"; then -- APR_ADDTO(libs, [`$apu_config --link-libtool --libs`]) -+ APR_ADDTO(libs, [`$apu_config --link-ld`]) - fi --APR_ADDTO(libs, [`$apr_config --link-libtool --libs` $LIBS]) -+APR_ADDTO(libs, [`$apr_config --link-ld` $LIBS]) - - APR_ADDTO(SERF_LIBS, [$libs]) - AC_SUBST(SERF_LIBS) +--- a/SConstruct ++++ b/SConstruct +@@ -345,8 +345,8 @@ else: + ### there is probably a better way to run/capture output. + ### env.ParseConfig() may be handy for getting this stuff into the build + if CALLOUT_OKAY: +- apr_libs = os.popen(env.subst('$APR --link-libtool --libs')).read().strip() +- apu_libs = os.popen(env.subst('$APU --link-libtool --libs')).read().strip() ++ apr_libs = os.popen(env.subst('$APR --link-ld')).read().strip() ++ apu_libs = os.popen(env.subst('$APU --link-ld')).read().strip() + else: + apr_libs = '' + apu_libs = '' diff -Nru serf-1.1.0/debian/rules serf-1.3.3/debian/rules --- serf-1.1.0/debian/rules 2014-01-07 01:18:14.000000000 +0000 +++ serf-1.3.3/debian/rules 2014-01-07 01:18:14.000000000 +0000 @@ -1,50 +1,34 @@ #!/usr/bin/make -f # -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. #export DH_VERBOSE=1 +DEB_LDFLAGS_MAINT_APPEND=-Wl,-z,defs +include /usr/share/dpkg/buildflags.mk include /usr/share/quilt/quilt.make -# These are used for cross-compiling and for saving the configure script -# from having to guess our platform (since we know it already) -DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) -DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) -ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) -CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE) -else -CROSS= --build $(DEB_BUILD_GNU_TYPE) -endif libdir := /usr/lib/$(DEB_HOST_MULTIARCH) includedir := /usr/include +libpkg := libserf-1-1 -configure: patch - autoconf - -BUILD/config.status: configure - dh_testdir - cp -f /usr/share/misc/config.sub build/config.sub - cp -f /usr/share/misc/config.guess build/config.guess - mkdir -p BUILD - cd BUILD; ../configure $(CROSS) --prefix=/usr \ - --libdir=$(libdir) --mandir=/usr/share/man \ - CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs" - +parallel := +ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + parallel := -j $(NUMJOBS) +endif build: build-arch build-indep build-indep: build-arch: debian/stamp-build -debian/stamp-build: BUILD/config.status +debian/stamp-build: patch dh_testdir - $(MAKE) -C BUILD + scons $(parallel) PREFIX=/usr LIBDIR=$(libdir) \ + CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" LINKFLAGS="$(LDFLAGS)" ifeq (, $(filter nocheck,$(DEB_BUILD_OPTIONS))) - $(MAKE) -C BUILD check + scons check endif touch $@ @@ -52,17 +36,18 @@ clean: unpatch dh_testdir - rm -fr BUILD - rm -f configure build/config.sub build/config.guess debian/stamp-* + scons -c + rm -f debian/stamp-* .saved_config .sconsign.dblite config.log - dh_clean + dh_clean -install: build +install: debian/stamp-build dh_testdir dh_testroot - dh_clean -k + dh_clean -k - $(MAKE) -C BUILD DESTDIR=$(CURDIR)/debian/tmp install + scons install --install=$(CURDIR)/debian/tmp + chrpath -d $(CURDIR)/debian/tmp/$(libdir)/*.so.* binary-indep: build install @@ -73,20 +58,20 @@ dh_installdocs -s NOTICE dh_installexamples -s dh_installman -s - install -d debian/libserf1/$(libdir) debian/libserf-dev/$(libdir) + install -d debian/$(libpkg)/$(libdir) debian/libserf-dev/$(libdir) install -d debian/libserf-dev/$(includedir) - mv debian/tmp$(libdir)/*.so.* debian/libserf1$(libdir)/ - mv debian/tmp$(libdir)/*.so debian/libserf-dev$(libdir)/ - mv debian/tmp$(libdir)/*.a debian/libserf-dev$(libdir)/ - mv debian/tmp$(libdir)/pkgconfig debian/libserf-dev$(libdir)/ - mv debian/tmp$(includedir)/* debian/libserf-dev$(includedir)/ - for p in $$(dh_listpackages -s -Nlibserf1); do \ - doc0=debian/$$p/usr/share/doc/libserf1; \ + mv debian/tmp/$(libdir)/*.so.* debian/$(libpkg)/$(libdir)/ + mv debian/tmp/$(libdir)/*.so debian/libserf-dev/$(libdir)/ + mv debian/tmp/$(libdir)/*.a debian/libserf-dev/$(libdir)/ + mv debian/tmp/$(libdir)/pkgconfig debian/libserf-dev/$(libdir)/ + mv debian/tmp/$(includedir)/* debian/libserf-dev/$(includedir)/ + for p in $$(dh_listpackages -s -N$(libpkg)); do \ + doc0=debian/$$p/usr/share/doc/$(libpkg); \ doc=debian/$$p/usr/share/doc/$$p; \ rm -f $$doc/changelog* $$doc/copyright; \ mv $$doc $$doc0; \ rmdir --ignore-fail-on-non-empty $$doc0; \ - ln -s libserf1 $$doc; \ + ln -s $(libpkg) $$doc; \ done; dh_link -s dh_strip -s --dbg-package=libserf1-dbg @@ -95,6 +80,7 @@ dh_makeshlibs -s dh_installdeb -s dh_shlibdeps -s + sed -i 's:libserf-private\(, *\)\?::' debian/*.substvars dh_lintian -s || true dh_gencontrol -s dh_md5sums -s diff -Nru serf-1.1.0/debian/watch serf-1.3.3/debian/watch --- serf-1.1.0/debian/watch 2014-01-07 01:18:14.000000000 +0000 +++ serf-1.3.3/debian/watch 2014-01-07 01:18:14.000000000 +0000 @@ -1,5 +1,5 @@ # Watch control file for uscan version=3 -http://code.google.com/p/serf/ \ - http://serf.googlecode.com/files/serf-(.*).tar.bz2 +http://code.google.com/p/serf/downloads/list?can=1 \ + .*/serf-(.*).tar.bz2 diff -Nru serf-1.1.0/incoming.c serf-1.3.3/incoming.c --- serf-1.1.0/incoming.c 2011-07-13 22:47:00.000000000 +0000 +++ serf-1.3.3/incoming.c 2013-02-25 07:14:18.000000000 +0000 @@ -152,7 +152,7 @@ rv = apr_socket_opt_set(l->skt, APR_SO_REUSEADDR, 1); if (rv) return rv; - + rv = apr_socket_bind(l->skt, sa); if (rv) return rv; diff -Nru serf-1.1.0/outgoing.c serf-1.3.3/outgoing.c --- serf-1.1.0/outgoing.c 2011-06-23 21:20:11.000000000 +0000 +++ serf-1.3.3/outgoing.c 2013-11-29 20:56:28.000000000 +0000 @@ -16,6 +16,7 @@ #include #include #include +#include #include "serf.h" #include "serf_bucket_util.h" @@ -29,8 +30,10 @@ apr_status_t status = APR_SUCCESS; if (conn->skt) { + serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt, "cleanup - "); status = apr_socket_close(conn->skt); conn->skt = NULL; + serf__log_nopref(SOCK_VERBOSE, "closed socket, status %d\n", status); } return status; @@ -71,11 +74,53 @@ { serf_connection_t *conn = data; + serf__log(CONN_VERBOSE, __FILE__, "cleaning up connection 0x%x\n", + conn); serf_connection_close(conn); return APR_SUCCESS; } +/* Check if there is data waiting to be sent over the socket. This can happen + in two situations: + - The connection queue has atleast one request with unwritten data. + - All requests are written and the ssl layer wrote some data while reading + the response. This can happen when the server triggers a renegotiation, + e.g. after the first and only request on that connection was received. + Returns 1 if data is pending on CONN, NULL if not. + If NEXT_REQ is not NULL, it will be filled in with the next available request + with unwritten data. */ +static int +request_or_data_pending(serf_request_t **next_req, serf_connection_t *conn) +{ + serf_request_t *request = conn->requests; + + while (request != NULL && request->req_bkt == NULL && + request->writing_started) + request = request->next; + + if (next_req) + *next_req = request; + + if (request != NULL) { + return 1; + } else if (conn->ostream_head) { + const char *dummy; + apr_size_t len; + apr_status_t status; + + status = serf_bucket_peek(conn->ostream_head, &dummy, + &len); + if (!SERF_BUCKET_READ_ERROR(status) && len) { + serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt, + "All requests written but still data pending.\n"); + return 1; + } + } + + return 0; +} + /* Update the pollset for this connection. We tweak the pollset based on * whether we want to read and/or write, given conditions within the * connection. If the connection is not (yet) in the pollset, then it @@ -103,32 +148,35 @@ /* Now put it back in with the correct read/write values. */ desc.reqevents = APR_POLLHUP | APR_POLLERR; - if (conn->requests) { + if (conn->requests && + conn->state != SERF_CONN_INIT) { /* If there are any outstanding events, then we want to read. */ /* ### not true. we only want to read IF we have sent some data */ desc.reqevents |= APR_POLLIN; - /* If the connection has unwritten data, or there are any requests - * that still have buckets to write out, then we want to write. - */ - if (conn->vec_len) - desc.reqevents |= APR_POLLOUT; - else { - serf_request_t *request = conn->requests; + /* Don't write if OpenSSL told us that it needs to read data first. */ + if (conn->stop_writing != 1) { - if ((conn->probable_keepalive_limit && - conn->completed_requests > conn->probable_keepalive_limit) || - (conn->max_outstanding_requests && - conn->completed_requests - conn->completed_responses >= - conn->max_outstanding_requests)) { - /* we wouldn't try to write any way right now. */ - } + /* If the connection is not closing down and + * has unwritten data or + * there are any requests that still have buckets to write out, + * then we want to write. + */ + if (conn->vec_len && + conn->state != SERF_CONN_CLOSING) + desc.reqevents |= APR_POLLOUT; else { - while (request != NULL && request->req_bkt == NULL && - request->written) - request = request->next; - if (request != NULL) + + if ((conn->probable_keepalive_limit && + conn->completed_requests > conn->probable_keepalive_limit) || + (conn->max_outstanding_requests && + conn->completed_requests - conn->completed_responses >= + conn->max_outstanding_requests)) { + /* we wouldn't try to write any way right now. */ + } + else if (request_or_data_pending(NULL, conn)) { desc.reqevents |= APR_POLLOUT; + } } } } @@ -169,6 +217,108 @@ #endif +static void destroy_ostream(serf_connection_t *conn) +{ + if (conn->ostream_head != NULL) { + serf_bucket_destroy(conn->ostream_head); + conn->ostream_head = NULL; + conn->ostream_tail = NULL; + } +} + +static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket) +{ + serf_connection_t *conn = baton; + conn->hit_eof = 1; + return APR_EAGAIN; +} + +static apr_status_t do_conn_setup(serf_connection_t *conn) +{ + apr_status_t status; + serf_bucket_t *ostream; + + if (conn->ostream_head == NULL) { + conn->ostream_head = serf_bucket_aggregate_create(conn->allocator); + } + + if (conn->ostream_tail == NULL) { + conn->ostream_tail = serf__bucket_stream_create(conn->allocator, + detect_eof, + conn); + } + + ostream = conn->ostream_tail; + + status = (*conn->setup)(conn->skt, + &conn->stream, + &ostream, + conn->setup_baton, + conn->pool); + if (status) { + /* extra destroy here since it wasn't added to the head bucket yet. */ + serf_bucket_destroy(conn->ostream_tail); + destroy_ostream(conn); + return status; + } + + serf_bucket_aggregate_append(conn->ostream_head, + ostream); + + return status; +} + +/* Set up the input and output stream buckets. + When a tunnel over an http proxy is needed, create a socket bucket and + empty aggregate bucket for sending and receiving unencrypted requests + over the socket. + + After the tunnel is there, or no tunnel was needed, ask the application + to create the input and output buckets, which should take care of the + [en/de]cryption. + */ + +static apr_status_t prepare_conn_streams(serf_connection_t *conn, + serf_bucket_t **istream, + serf_bucket_t **ostreamt, + serf_bucket_t **ostreamh) +{ + apr_status_t status; + + if (conn->stream == NULL) { + conn->latency = apr_time_now() - conn->connect_time; + } + + /* Do we need a SSL tunnel first? */ + if (conn->state == SERF_CONN_CONNECTED) { + /* If the connection does not have an associated bucket, then + * call the setup callback to get one. + */ + if (conn->stream == NULL) { + status = do_conn_setup(conn); + if (status) { + return status; + } + } + *ostreamt = conn->ostream_tail; + *ostreamh = conn->ostream_head; + *istream = conn->stream; + } else { + /* SSL tunnel needed and not set up yet, get a direct unencrypted + stream for this socket */ + if (conn->stream == NULL) { + *istream = serf_bucket_socket_create(conn->skt, + conn->allocator); + } + /* Don't create the ostream bucket chain including the ssl_encrypt + bucket yet. This ensure the CONNECT request is sent unencrypted + to the proxy. */ + *ostreamt = *ostreamh = conn->ssltunnel_ostream; + } + + return APR_SUCCESS; +} + /* Create and connect sockets for any connections which don't have them * yet. This is the core of our lazy-connect behavior. */ @@ -178,9 +328,9 @@ for (i = ctx->conns->nelts; i--; ) { serf_connection_t *conn = GET_CONN(ctx, i); + serf__authn_info_t *authn_info; apr_status_t status; apr_socket_t *skt; - apr_sockaddr_t *serv_addr; conn->seen_in_pollset = 0; @@ -199,18 +349,15 @@ apr_pool_clear(conn->skt_pool); apr_pool_cleanup_register(conn->skt_pool, conn, clean_skt, clean_skt); - /* Do we have to connect to a proxy server? */ - if (ctx->proxy_address) - serv_addr = ctx->proxy_address; - else - serv_addr = conn->address; - - if ((status = apr_socket_create(&skt, serv_addr->family, - SOCK_STREAM, + status = apr_socket_create(&skt, conn->address->family, + SOCK_STREAM, #if APR_MAJOR_VERSION > 0 - APR_PROTO_TCP, + APR_PROTO_TCP, #endif - conn->skt_pool)) != APR_SUCCESS) + conn->skt_pool); + serf__log(SOCK_VERBOSE, __FILE__, + "created socket for conn 0x%x, status %d\n", conn, status); + if (status != APR_SUCCESS) return status; /* Set the socket to be non-blocking */ @@ -225,11 +372,18 @@ /* Configured. Store it into the connection now. */ conn->skt = skt; + /* Remember time when we started connecting to server to calculate + network latency. */ + conn->connect_time = apr_time_now(); + /* Now that the socket is set up, let's connect it. This should * return immediately. */ - if ((status = apr_socket_connect(skt, - serv_addr)) != APR_SUCCESS) { + status = apr_socket_connect(skt, conn->address); + serf__log_skt(SOCK_VERBOSE, __FILE__, skt, + "connected socket for conn 0x%x, status %d\n", + conn, status); + if (status != APR_SUCCESS) { if (!APR_STATUS_IS_EINPROGRESS(status)) return status; } @@ -242,38 +396,44 @@ prepare this connection (it might be possible to skip some part of the handshaking). */ if (ctx->proxy_address) { - if (conn->ctx->proxy_authn_info.scheme) - conn->ctx->proxy_authn_info.scheme->init_conn_func(407, conn, - conn->pool); + authn_info = &ctx->proxy_authn_info; + if (authn_info->scheme) { + authn_info->scheme->init_conn_func(authn_info->scheme, 407, + conn, conn->pool); + } } - if (conn->ctx->authn_info.scheme) - conn->ctx->authn_info.scheme->init_conn_func(401, conn, - conn->pool); + authn_info = serf__get_authn_info_for_server(conn); + if (authn_info->scheme) { + authn_info->scheme->init_conn_func(authn_info->scheme, 401, + conn, conn->pool); + } /* Does this connection require a SSL tunnel over the proxy? */ if (ctx->proxy_address && strcmp(conn->host_info.scheme, "https") == 0) serf__ssltunnel_connect(conn); - else + else { + serf_bucket_t *dummy1, *dummy2; + conn->state = SERF_CONN_CONNECTED; + + status = prepare_conn_streams(conn, &conn->stream, + &dummy1, &dummy2); + if (status) { + return status; + } + } } return APR_SUCCESS; } -static apr_status_t no_more_writes(serf_connection_t *conn, - serf_request_t *request) +static apr_status_t no_more_writes(serf_connection_t *conn) { /* Note that we should hold new requests until we open our new socket. */ conn->state = SERF_CONN_CLOSING; - - /* We can take the *next* request in our list and assume it hasn't - * been written yet and 'save' it for the new socket. - */ - conn->hold_requests = request->next; - conn->hold_requests_tail = conn->requests_tail; - request->next = NULL; - conn->requests_tail = request; + serf__log(CONN_VERBOSE, __FILE__, "stop writing on conn 0x%x\n", + conn); /* Clear our iovec. */ conn->vec_len = 0; @@ -390,15 +550,6 @@ &desc, conn); } -static void destroy_ostream(serf_connection_t *conn) -{ - if (conn->ostream_head != NULL) { - serf_bucket_destroy(conn->ostream_head); - conn->ostream_head = NULL; - conn->ostream_tail = NULL; - } -} - /* A socket was closed, inform the application. */ static void handle_conn_closed(serf_connection_t *conn, apr_status_t status) { @@ -411,52 +562,47 @@ { serf_context_t *ctx = conn->ctx; apr_status_t status; - serf_request_t *old_reqs, *held_reqs, *held_reqs_tail; + serf_request_t *old_reqs; conn->probable_keepalive_limit = conn->completed_responses; conn->completed_requests = 0; conn->completed_responses = 0; old_reqs = conn->requests; - held_reqs = conn->hold_requests; - held_reqs_tail = conn->hold_requests_tail; - - if (conn->state == SERF_CONN_CLOSING) { - conn->hold_requests = NULL; - conn->hold_requests_tail = NULL; - } conn->requests = NULL; conn->requests_tail = NULL; + /* Handle all outstanding requests. These have either not been written yet, + or have been written but the expected reply wasn't received yet. */ while (old_reqs) { /* If we haven't started to write the connection, bring it over - * unchanged to our new socket. Otherwise, call the cancel function. + * unchanged to our new socket. + * Do not copy a CONNECT request to the new connection, the ssl tunnel + * setup code will create a new CONNECT request already. */ - if (requeue_requests && !old_reqs->written) { + if (requeue_requests && !old_reqs->writing_started && + !old_reqs->ssltunnel) { + serf_request_t *req = old_reqs; old_reqs = old_reqs->next; req->next = NULL; link_requests(&conn->requests, &conn->requests_tail, req); } else { + /* Request has been consumed, or we don't want to requeue the + request. Either way, inform the application that the request + is cancelled. */ cancel_request(old_reqs, &old_reqs, requeue_requests); } } - if (conn->requests_tail) { - conn->requests_tail->next = held_reqs; - } - else { - conn->requests = held_reqs; - } - if (held_reqs_tail) { - conn->requests_tail = held_reqs_tail; - } - + /* Requests queue has been prepared for a new socket, close the old one. */ if (conn->skt != NULL) { remove_connection(ctx, conn); status = apr_socket_close(conn->skt); + serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt, + "closed socket, status %d\n", status); if (conn->closed != NULL) { handle_conn_closed(conn, status); } @@ -477,6 +623,8 @@ conn->ctx->dirty_pollset = 1; conn->state = SERF_CONN_INIT; + serf__log(CONN_VERBOSE, __FILE__, "reset connection 0x%x\n", conn); + conn->status = APR_SUCCESS; /* Let our context know that we've 'reset' the socket already. */ @@ -493,15 +641,24 @@ status = apr_socket_sendv(conn->skt, conn->vec, conn->vec_len, &written); + if (status && !APR_STATUS_IS_EAGAIN(status)) + serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt, + "socket_sendv error %d\n", status); /* did we write everything? */ if (written) { apr_size_t len = 0; int i; + serf__log_skt(SOCK_MSG_VERBOSE, __FILE__, conn->skt, + "--- socket_sendv:\n"); + for (i = 0; i < conn->vec_len; i++) { len += conn->vec[i].iov_len; if (written < len) { + serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s", + conn->vec[i].iov_len - (len - written), + conn->vec[i].iov_base); if (i) { memmove(conn->vec, &conn->vec[i], sizeof(struct iovec) * (conn->vec_len - i)); @@ -510,11 +667,15 @@ conn->vec[0].iov_base = (char *)conn->vec[0].iov_base + (conn->vec[0].iov_len - (len - written)); conn->vec[0].iov_len = len - written; break; + } else { + serf__log_nopref(SOCK_MSG_VERBOSE, "%.*s", + conn->vec[i].iov_len, conn->vec[i].iov_base); } } if (len == written) { conn->vec_len = 0; } + serf__log_nopref(SOCK_MSG_VERBOSE, "-(%d)-\n", written); /* Log progress information */ serf__context_progress_delta(conn->ctx, 0, written); @@ -523,100 +684,32 @@ return status; } -static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket) -{ - serf_connection_t *conn = baton; - conn->hit_eof = 1; - return APR_EAGAIN; -} - -static apr_status_t do_conn_setup(serf_connection_t *conn) +static apr_status_t setup_request(serf_request_t *request) { + serf_connection_t *conn = request->conn; apr_status_t status; - serf_bucket_t *ostream; - - if (conn->ostream_head == NULL) { - conn->ostream_head = serf_bucket_aggregate_create(conn->allocator); - } - - if (conn->ostream_tail == NULL) { - conn->ostream_tail = serf__bucket_stream_create(conn->allocator, - detect_eof, - conn); - } - - ostream = conn->ostream_tail; - - status = (*conn->setup)(conn->skt, - &conn->stream, - &ostream, - conn->setup_baton, - conn->pool); - if (status) { - /* extra destroy here since it wasn't added to the head bucket yet. */ - serf_bucket_destroy(conn->ostream_tail); - destroy_ostream(conn); - return status; - } - - serf_bucket_aggregate_append(conn->ostream_head, - ostream); + /* Now that we are about to serve the request, allocate a pool. */ + apr_pool_create(&request->respool, conn->pool); + request->allocator = serf_bucket_allocator_create(request->respool, + NULL, NULL); + apr_pool_cleanup_register(request->respool, request, + clean_resp, clean_resp); + + /* Fill in the rest of the values for the request. */ + status = request->setup(request, request->setup_baton, + &request->req_bkt, + &request->acceptor, + &request->acceptor_baton, + &request->handler, + &request->handler_baton, + request->respool); return status; } -/* Set up the input and output stream buckets. - When a tunnel over an http proxy is needed, create a socket bucket and - empty aggregate bucket for sending and receiving unencrypted requests - over the socket. - - After the tunnel is there, or no tunnel was needed, ask the application - to create the input and output buckets, which should take care of the - [en/de]cryption. -*/ - -static apr_status_t prepare_conn_streams(serf_connection_t *conn, - serf_bucket_t **istream, - serf_bucket_t **ostreamt, - serf_bucket_t **ostreamh) -{ - apr_status_t status; - - /* Do we need a SSL tunnel first? */ - if (conn->state == SERF_CONN_CONNECTED) { - /* If the connection does not have an associated bucket, then - * call the setup callback to get one. - */ - if (conn->stream == NULL) { - status = do_conn_setup(conn); - if (status) { - return status; - } - } - *ostreamt = conn->ostream_tail; - *ostreamh = conn->ostream_head; - *istream = conn->stream; - } else { - /* SSL tunnel needed and not set up yet, get a direct unencrypted - stream for this socket */ - if (conn->stream == NULL) { - *istream = serf_bucket_socket_create(conn->skt, - conn->allocator); - } - /* Don't create the ostream bucket chain including the ssl_encrypt - bucket yet. This ensure the CONNECT request is sent unencrypted - to the proxy. */ - *ostreamt = *ostreamh = conn->ssltunnel_ostream; - } - - return APR_SUCCESS; -} - /* write data out to the connection */ static apr_status_t write_to_connection(serf_connection_t *conn) { - serf_request_t *request = conn->requests; - if (conn->probable_keepalive_limit && conn->completed_requests > conn->probable_keepalive_limit) { @@ -627,21 +720,16 @@ return APR_SUCCESS; } - /* Find a request that has data which needs to be delivered. */ - while (request != NULL && - request->req_bkt == NULL && request->written) - request = request->next; - - /* assert: request != NULL || conn->vec_len */ - /* Keep reading and sending until we run out of stuff to read, or * writing would block. */ while (1) { + serf_request_t *request; int stop_reading = 0; apr_status_t status; apr_status_t read_status; - serf_bucket_t *ostreamt, *ostreamh; + serf_bucket_t *ostreamt; + serf_bucket_t *ostreamh; int max_outstanding_requests = conn->max_outstanding_requests; /* If we're setting up an ssl tunnel, we can't send real requests @@ -667,8 +755,10 @@ */ if (APR_STATUS_IS_EAGAIN(status)) return APR_SUCCESS; - if (APR_STATUS_IS_EPIPE(status)) - return no_more_writes(conn, request); + if (APR_STATUS_IS_EPIPE(status) || + APR_STATUS_IS_ECONNRESET(status) || + APR_STATUS_IS_ECONNABORTED(status)) + return no_more_writes(conn); if (status) return status; } @@ -679,14 +769,11 @@ /* We may need to move forward to a request which has something * to write. */ - while (request != NULL && - request->req_bkt == NULL && request->written) - request = request->next; - - if (request == NULL) { + if (!request_or_data_pending(&request, conn)) { /* No more requests (with data) are registered with the - * connection. Let's update the pollset so that we don't - * try to write to this socket again. + * connection, and no data is pending on the outgoing stream. + * Let's update the pollset so that we don't try to write to this + * socket again. */ conn->dirty_conn = 1; conn->ctx->dirty_pollset = 1; @@ -698,33 +785,26 @@ return status; } - if (request->req_bkt == NULL) { - /* Now that we are about to serve the request, allocate a pool. */ - apr_pool_create(&request->respool, conn->pool); - request->allocator = serf_bucket_allocator_create(request->respool, - NULL, NULL); - apr_pool_cleanup_register(request->respool, request, - clean_resp, clean_resp); - - /* Fill in the rest of the values for the request. */ - read_status = request->setup(request, request->setup_baton, - &request->req_bkt, - &request->acceptor, - &request->acceptor_baton, - &request->handler, - &request->handler_baton, - request->respool); - - if (read_status) { - /* Something bad happened. Propagate any errors. */ - return read_status; + if (request) { + if (request->req_bkt == NULL) { + read_status = setup_request(request); + if (read_status) { + /* Something bad happened. Propagate any errors. */ + return read_status; + } } - request->written = 1; - serf_bucket_aggregate_append(ostreamt, request->req_bkt); + if (!request->writing_started) { + request->writing_started = 1; + serf_bucket_aggregate_append(ostreamt, request->req_bkt); + } } /* ### optimize at some point by using read_for_sendfile */ + /* TODO: now that read_iovec will effectively try to return as much + data as available, we probably don't want to read ALL_AVAIL, but + a lower number, like the size of one or a few TCP packets, the + available TCP buffer size ... */ read_status = serf_bucket_read_iovec(ostreamh, SERF_READ_ALL_AVAIL, IOV_MAX, @@ -732,17 +812,24 @@ &conn->vec_len); if (!conn->hit_eof) { - if (APR_STATUS_IS_EAGAIN(read_status) || - read_status == SERF_ERROR_WAIT_CONN) { + if (APR_STATUS_IS_EAGAIN(read_status)) { /* We read some stuff, but should not try to read again. */ stop_reading = 1; - - /* ### we should avoid looking for writability for a while so - ### that (hopefully) something will appear in the bucket so - ### we can actually write something. otherwise, we could - ### end up in a CPU spin: socket wants something, but we - ### don't have anything (and keep returning EAGAIN) - */ + } + else if (read_status == SERF_ERROR_WAIT_CONN) { + /* The bucket told us that it can't provide more data until + more data is read from the socket. This normally happens + during a SSL handshake. + + We should avoid looking for writability for a while so + that (hopefully) something will appear in the bucket so + we can actually write something. otherwise, we could + end up in a CPU spin: socket wants something, but we + don't have anything (and keep returning EAGAIN) + */ + conn->stop_writing = 1; + conn->dirty_conn = 1; + conn->ctx->dirty_pollset = 1; } else if (read_status && !APR_STATUS_IS_EOF(read_status)) { /* Something bad happened. Propagate any errors. */ @@ -761,9 +848,10 @@ if (APR_STATUS_IS_EAGAIN(status)) return APR_SUCCESS; if (APR_STATUS_IS_EPIPE(status)) - return no_more_writes(conn, request); - if (APR_STATUS_IS_ECONNRESET(status)) { - return no_more_writes(conn, request); + return no_more_writes(conn); + if (APR_STATUS_IS_ECONNRESET(status) || + APR_STATUS_IS_ECONNABORTED(status)) { + return no_more_writes(conn); } if (status) return status; @@ -771,8 +859,12 @@ if (read_status == SERF_ERROR_WAIT_CONN) { stop_reading = 1; + conn->stop_writing = 1; + conn->dirty_conn = 1; + conn->ctx->dirty_pollset = 1; } - else if (read_status && conn->hit_eof && conn->vec_len == 0) { + else if (request && read_status && conn->hit_eof && + conn->vec_len == 0) { /* If we hit the end of the request bucket and all of its data has * been written, then clear it out to signify that we're done * sending the request. On the next iteration through this loop: @@ -836,8 +928,7 @@ If the authentication was tried, but failed, pass the response to the application, maybe it can do better. */ - if (APR_STATUS_IS_EOF(status) || - APR_STATUS_IS_EAGAIN(status)) { + if (status) { return status; } } @@ -876,6 +967,57 @@ return status; } + +apr_status_t +serf__provide_credentials(serf_context_t *ctx, + char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) +{ + serf_connection_t *conn = request->conn; + serf_request_t *authn_req = request; + apr_status_t status; + + if (request->ssltunnel == 1 && + conn->state == SERF_CONN_SETUP_SSLTUNNEL) { + /* This is a CONNECT request to set up an SSL tunnel over a proxy. + This request is created by serf, so if the proxy requires + authentication, we can't ask the application for credentials with + this request. + + Solution: setup the first request created by the application on + this connection, and use that request and its handler_baton to + call back to the application. */ + + authn_req = request->next; + /* assert: app_request != NULL */ + if (!authn_req) + return APR_EGENERAL; + + if (!authn_req->req_bkt) { + apr_status_t status; + + status = setup_request(authn_req); + /* If we can't setup a request, don't bother setting up the + ssl tunnel. */ + if (status) + return status; + } + } + + /* Ask the application. */ + status = (*ctx->cred_cb)(username, password, + authn_req, authn_req->handler_baton, + code, authn_type, realm, pool); + if (status) + return status; + + return APR_SUCCESS; +} + /* read data from the connection */ static apr_status_t read_from_connection(serf_connection_t *conn) { @@ -888,6 +1030,14 @@ */ serf_request_t *request = conn->requests; + /* If the stop_writing flag was set on the connection, reset it now because + there is some data to read. */ + if (conn->stop_writing) { + conn->stop_writing = 0; + conn->dirty_conn = 1; + conn->ctx->dirty_pollset = 1; + } + /* assert: request != NULL */ if ((status = apr_pool_create(&tmppool, conn->pool)) != APR_SUCCESS) @@ -929,31 +1079,38 @@ * 2) Doing the initial SSL handshake - we'll get EAGAIN * as the SSL buckets will hide the handshake from us * but not return any data. + * 3) When the server sends us an SSL alert. * * In these cases, we should not receive any actual user data. * - * If we see an EOF (due to an expired timeout), we'll reset the + * 4) When the server sends a error response, like 408 Request timeout. + * This response should be passed to the application. + * + * If we see an EOF (due to either an expired timeout or the server + * sending the SSL 'close notify' shutdown alert), we'll reset the * connection and open a new one. */ - if (request->req_bkt || !request->written) { + if (request->req_bkt || !request->writing_started) { const char *data; apr_size_t len; - status = serf_bucket_read(conn->stream, SERF_READ_ALL_AVAIL, - &data, &len); + status = serf_bucket_peek(conn->stream, &data, &len); - if (!status && len) { - status = APR_EGENERAL; - } - else if (APR_STATUS_IS_EOF(status)) { + if (APR_STATUS_IS_EOF(status)) { reset_connection(conn, 1); status = APR_SUCCESS; + goto error; } - else if (APR_STATUS_IS_EAGAIN(status)) { + else if (APR_STATUS_IS_EAGAIN(status) && !len) { status = APR_SUCCESS; + goto error; + } else if (status && !APR_STATUS_IS_EAGAIN(status)) { + /* Read error */ + goto error; } - goto error; + /* Unexpected response from the server */ + } /* If the request doesn't have a response bucket, then call the @@ -969,12 +1126,21 @@ status = handle_response(request, tmppool); /* Some systems will not generate a HUP poll event so we have to - * handle the ECONNRESET issue here. + * handle the ECONNRESET issue and ECONNABORT here. */ if (APR_STATUS_IS_ECONNRESET(status) || + APR_STATUS_IS_ECONNABORTED(status) || status == SERF_ERROR_REQUEST_LOST) { - reset_connection(conn, 1); - status = APR_SUCCESS; + /* If the connection had ever been good, be optimistic & try again. + * If it has never tried again (incl. a retry), fail. + */ + if (conn->completed_responses) { + reset_connection(conn, 1); + status = APR_SUCCESS; + } + else if (status == SERF_ERROR_REQUEST_LOST) { + status = SERF_ERROR_ABORTED_CONNECTION; + } goto error; } @@ -982,6 +1148,14 @@ * treat that as a success. */ if (APR_STATUS_IS_EAGAIN(status)) { + /* It is possible that while reading the response, the ssl layer + has prepared some data to send. If this was the last request, + serf will not check for socket writability, so force this here. + */ + if (request_or_data_pending(&request, conn) && !request) { + conn->dirty_conn = 1; + conn->ctx->dirty_pollset = 1; + } status = APR_SUCCESS; goto error; } @@ -1001,9 +1175,11 @@ goto error; } - /* The request has been fully-delivered, and the response has - * been fully-read. Remove it from our queue and loop to read - * another response. + /* The response has been fully-read, so that means the request has + * either been fully-delivered (most likely), or that we don't need to + * write the rest of it anymore, e.g. when a 408 Request timeout was + $ received. + * Remove it from our queue and loop to read another response. */ conn->requests = request->next; @@ -1044,7 +1220,7 @@ * update the pollset. We don't want to read from this socket any * more. We are definitely done with this loop, too. */ - if (request == NULL || !request->written) { + if (request == NULL || !request->writing_started) { conn->dirty_conn = 1; conn->ctx->dirty_pollset = 1; status = APR_SUCCESS; @@ -1081,8 +1257,13 @@ if ((events & APR_POLLHUP) != 0) { /* The connection got reset by the server. On Windows this can happen when all data is read, so just cleanup the connection and open - a new one. */ - return reset_connection(conn, 1); + a new one. + If we haven't had any successful responses on this connection, + then error out as it is likely a server issue. */ + if (conn->completed_responses) { + return reset_connection(conn, 1); + } + return SERF_ERROR_ABORTED_CONNECTION; } if ((events & APR_POLLERR) != 0) { /* We might be talking to a buggy HTTP server that doesn't @@ -1095,6 +1276,41 @@ if (conn->completed_requests && !conn->probable_keepalive_limit) { return reset_connection(conn, 1); } +#ifdef SO_ERROR + /* If possible, get the error from the platform's socket layer and + convert it to an APR status code. */ + { + apr_os_sock_t osskt; + if (!apr_os_sock_get(&osskt, conn->skt)) { + int error; + apr_socklen_t l = sizeof(error); + + if (!getsockopt(osskt, SOL_SOCKET, SO_ERROR, (char*)&error, + &l)) { + status = APR_FROM_OS_ERROR(error); + + /* Handle fallback for multi-homed servers. + + ### Improve algorithm to find better than just 'next'? + + Current Windows versions already handle re-ordering for + api users by using statistics on the recently failed + connections to order the list of addresses. */ + if (conn->completed_requests == 0 + && conn->address->next != NULL + && (APR_STATUS_IS_ECONNREFUSED(status) + || APR_STATUS_IS_TIMEUP(status) + || APR_STATUS_IS_ENETUNREACH(status))) { + + conn->address = conn->address->next; + return reset_connection(conn, 1); + } + + return status; + } + } + } +#endif return APR_EGENERAL; } if ((events & APR_POLLOUT) != 0) { @@ -1117,7 +1333,8 @@ conn->ctx = ctx; conn->status = APR_SUCCESS; - conn->address = address; + /* Ignore server address if proxy was specified. */ + conn->address = ctx->proxy_address ? ctx->proxy_address : address; conn->setup = setup; conn->setup_baton = setup_baton; conn->closed = closed; @@ -1131,16 +1348,21 @@ conn->baton.u.conn = conn; conn->hit_eof = 0; conn->state = SERF_CONN_INIT; + conn->latency = -1; /* unknown */ /* Create a subpool for our connection. */ apr_pool_create(&conn->skt_pool, conn->pool); /* register a cleanup */ - apr_pool_cleanup_register(conn->pool, conn, clean_conn, apr_pool_cleanup_null); + apr_pool_cleanup_register(conn->pool, conn, clean_conn, + apr_pool_cleanup_null); /* Add the connection to the context. */ *(serf_connection_t **)apr_array_push(ctx->conns) = conn; + serf__log(CONN_VERBOSE, __FILE__, "created connection 0x%x\n", + conn); + return conn; } @@ -1154,16 +1376,24 @@ void *closed_baton, apr_pool_t *pool) { - apr_status_t status; + apr_status_t status = APR_SUCCESS; serf_connection_t *c; - apr_sockaddr_t *host_address; + apr_sockaddr_t *host_address = NULL; - /* Parse the url, store the address of the server. */ - status = apr_sockaddr_info_get(&host_address, - host_info.hostname, - APR_UNSPEC, host_info.port, 0, pool); - if (status) - return status; + /* Set the port number explicitly, needed to create the socket later. */ + if (!host_info.port) { + host_info.port = apr_uri_port_of_scheme(host_info.scheme); + } + + /* Only lookup the address of the server if no proxy server was + configured. */ + if (!ctx->proxy_address) { + status = apr_sockaddr_info_get(&host_address, + host_info.hostname, + APR_UNSPEC, host_info.port, 0, pool); + if (status) + return status; + } c = serf_connection_create(ctx, host_address, setup, setup_baton, closed, closed_baton, pool); @@ -1171,8 +1401,14 @@ /* We're not interested in the path following the hostname. */ c->host_url = apr_uri_unparse(c->pool, &host_info, - APR_URI_UNP_OMITPATHINFO); - c->host_info = host_info; + APR_URI_UNP_OMITPATHINFO | + APR_URI_UNP_OMITUSERINFO); + + /* Store the host info without the path on the connection. */ + (void)apr_uri_parse(c->pool, c->host_url, &(c->host_info)); + if (!c->host_info.port) { + c->host_info.port = apr_uri_port_of_scheme(c->host_info.scheme); + } *conn = c; @@ -1203,6 +1439,9 @@ if (conn->skt != NULL) { remove_connection(ctx, conn); status = apr_socket_close(conn->skt); + serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt, + "closed socket, status %d\n", + status); if (conn->closed != NULL) { handle_conn_closed(conn, status); } @@ -1213,6 +1452,8 @@ conn->stream = NULL; } + destroy_ostream(conn); + /* Remove the connection from the context. We don't want to * deal with it any more. */ @@ -1225,6 +1466,9 @@ } --ctx->conns->nelts; + serf__log(CONN_VERBOSE, __FILE__, "closed connection 0x%x\n", + conn); + /* Found the connection. Closed it. All done. */ return APR_SUCCESS; } @@ -1240,6 +1484,15 @@ serf_connection_t *conn, unsigned int max_requests) { + if (max_requests == 0) + serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt, + "Set max. nr. of outstanding requests for this " + "connection to unlimited.\n"); + else + serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt, + "Limit max. nr. of outstanding requests for this " + "connection to %u.\n", max_requests); + conn->max_outstanding_requests = max_requests; } @@ -1258,11 +1511,12 @@ conn->async_handler_baton = handler_baton; } - -serf_request_t *serf_connection_request_create( - serf_connection_t *conn, - serf_request_setup_t setup, - void *setup_baton) +static serf_request_t * +create_request(serf_connection_t *conn, + serf_request_setup_t setup, + void *setup_baton, + int priority, + int ssltunnel) { serf_request_t *request; @@ -1274,66 +1528,70 @@ request->respool = NULL; request->req_bkt = NULL; request->resp_bkt = NULL; - request->priority = 0; - request->written = 0; + request->priority = priority; + request->writing_started = 0; + request->ssltunnel = ssltunnel; request->next = NULL; - - /* Link the request to the end of the request chain. */ - if (conn->state == SERF_CONN_CLOSING) { - link_requests(&conn->hold_requests, &conn->hold_requests_tail, request); - } - else { - link_requests(&conn->requests, &conn->requests_tail, request); - - /* Ensure our pollset becomes writable in context run */ - conn->ctx->dirty_pollset = 1; - conn->dirty_conn = 1; - } + request->auth_baton = NULL; return request; } - -serf_request_t *serf_connection_priority_request_create( +serf_request_t *serf_connection_request_create( serf_connection_t *conn, serf_request_setup_t setup, void *setup_baton) { serf_request_t *request; + + request = create_request(conn, setup, setup_baton, + 0, /* priority */ + 0 /* ssl tunnel */); + + /* Link the request to the end of the request chain. */ + link_requests(&conn->requests, &conn->requests_tail, request); + + /* Ensure our pollset becomes writable in context run */ + conn->ctx->dirty_pollset = 1; + conn->dirty_conn = 1; + + return request; +} + +static serf_request_t * +priority_request_create(serf_connection_t *conn, + int ssltunnelreq, + serf_request_setup_t setup, + void *setup_baton) +{ + serf_request_t *request; serf_request_t *iter, *prev; - request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request)); - request->conn = conn; - request->setup = setup; - request->setup_baton = setup_baton; - request->handler = NULL; - request->respool = NULL; - request->req_bkt = NULL; - request->resp_bkt = NULL; - request->priority = 1; - request->written = 0; - request->next = NULL; + request = create_request(conn, setup, setup_baton, + 1, /* priority */ + ssltunnelreq); - /* Link the new request after the last written request, but before all - upcoming requests. */ - if (conn->state == SERF_CONN_CLOSING) { - iter = conn->hold_requests; - } - else { - iter = conn->requests; - } + /* Link the new request after the last written request. */ + iter = conn->requests; prev = NULL; /* Find a request that has data which needs to be delivered. */ - while (iter != NULL && iter->req_bkt == NULL && iter->written) { + while (iter != NULL && iter->req_bkt == NULL && iter->writing_started) { prev = iter; iter = iter->next; } - /* Advance to next non priority request */ - while (iter != NULL && iter->priority) { - prev = iter; - iter = iter->next; + /* A CONNECT request to setup an ssltunnel has absolute priority over all + other requests on the connection, so: + a. add it first to the queue + b. ensure that other priority requests are added after the CONNECT + request */ + if (!request->ssltunnel) { + /* Advance to next non priority request */ + while (iter != NULL && iter->priority) { + prev = iter; + iter = iter->next; + } } if (prev) { @@ -1341,29 +1599,47 @@ prev->next = request; } else { request->next = iter; - if (conn->state == SERF_CONN_CLOSING) { - conn->hold_requests = request; - } - else { - conn->requests = request; - } + conn->requests = request; } - if (conn->state != SERF_CONN_CLOSING) { - /* Ensure our pollset becomes writable in context run */ - conn->ctx->dirty_pollset = 1; - conn->dirty_conn = 1; - } + /* Ensure our pollset becomes writable in context run */ + conn->ctx->dirty_pollset = 1; + conn->dirty_conn = 1; return request; } +serf_request_t *serf_connection_priority_request_create( + serf_connection_t *conn, + serf_request_setup_t setup, + void *setup_baton) +{ + return priority_request_create(conn, + 0, /* not a ssltunnel CONNECT request */ + setup, setup_baton); +} + +serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn, + serf_request_setup_t setup, + void *setup_baton) +{ + return priority_request_create(conn, + 1, /* This is a ssltunnel CONNECT request */ + setup, setup_baton); +} apr_status_t serf_request_cancel(serf_request_t *request) { return cancel_request(request, &request->conn->requests, 0); } +apr_status_t serf_request_is_written(serf_request_t *request) +{ + if (request->writing_started && !request->req_bkt) + return APR_SUCCESS; + + return APR_EBUSY; +} apr_pool_t *serf_request_get_pool(const serf_request_t *request) { @@ -1405,27 +1681,64 @@ serf_bucket_t *req_bkt, *hdrs_bkt; serf_connection_t *conn = request->conn; serf_context_t *ctx = conn->ctx; + int ssltunnel; + + ssltunnel = ctx->proxy_address && + (strcmp(conn->host_info.scheme, "https") == 0); req_bkt = serf_bucket_request_create(method, uri, body, allocator); hdrs_bkt = serf_bucket_request_get_headers(req_bkt); - /* Proxy? */ - if (ctx->proxy_address && conn->host_url) + /* Use absolute uri's in requests to a proxy. USe relative uri's in + requests directly to a server or sent through an SSL tunnel. */ + if (ctx->proxy_address && conn->host_url && + !(ssltunnel && !request->ssltunnel)) { + serf_bucket_request_set_root(req_bkt, conn->host_url); + } if (conn->host_info.hostinfo) serf_bucket_headers_setn(hdrs_bkt, "Host", conn->host_info.hostinfo); - /* Setup server authorization headers */ - if (ctx->authn_info.scheme) - ctx->authn_info.scheme->setup_request_func(401, conn, method, uri, + /* Setup server authorization headers, unless this is a CONNECT request. */ + if (!request->ssltunnel) { + serf__authn_info_t *authn_info; + authn_info = serf__get_authn_info_for_server(conn); + if (authn_info->scheme) + authn_info->scheme->setup_request_func(HOST, 0, conn, request, + method, uri, hdrs_bkt); + } - /* Setup proxy authorization headers */ - if (ctx->proxy_authn_info.scheme) - ctx->proxy_authn_info.scheme->setup_request_func(407, conn, method, - uri, hdrs_bkt); + /* Setup proxy authorization headers. + Don't set these headers on the requests to the server if we're using + an SSL tunnel, only on the CONNECT request to setup the tunnel. */ + if (ctx->proxy_authn_info.scheme) { + if (strcmp(conn->host_info.scheme, "https") == 0) { + if (request->ssltunnel) + ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn, + request, + method, uri, + hdrs_bkt); + } else { + ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn, + request, + method, uri, + hdrs_bkt); + } + } return req_bkt; } + +apr_interval_time_t serf_connection_get_latency(serf_connection_t *conn) +{ + if (conn->ctx->proxy_address) { + /* Detecting network latency for proxied connection is not implemented + yet. */ + return -1; + } + + return conn->latency; +} diff -Nru serf-1.1.0/serf.h serf-1.3.3/serf.h --- serf-1.1.0/serf.h 2012-03-20 19:42:49.000000000 +0000 +++ serf-1.3.3/serf.h 2013-11-29 20:36:01.000000000 +0000 @@ -59,47 +59,61 @@ * Serf-specific error codes */ #define SERF_ERROR_RANGE 100 +#define SERF_ERROR_START (APR_OS_START_USERERR + SERF_ERROR_RANGE) /* This code is for when this is the last response on this connection: * i.e. do not send any more requests on this connection or expect * any more responses. */ -#define SERF_ERROR_CLOSING (APR_OS_START_USERERR + SERF_ERROR_RANGE + 1) +#define SERF_ERROR_CLOSING (SERF_ERROR_START + 1) /* This code is for when the connection terminated before the request * could be processed on the other side. */ -#define SERF_ERROR_REQUEST_LOST (APR_OS_START_USERERR + SERF_ERROR_RANGE + 2) +#define SERF_ERROR_REQUEST_LOST (SERF_ERROR_START + 2) /* This code is for when the connection is blocked - we can not proceed * until something happens - generally due to SSL negotiation-like behavior * where a write() is blocked until a read() is processed. */ -#define SERF_ERROR_WAIT_CONN (APR_OS_START_USERERR + SERF_ERROR_RANGE + 3) +#define SERF_ERROR_WAIT_CONN (SERF_ERROR_START + 3) /* This code is for when something went wrong during deflating compressed * data e.g. a CRC error. */ -#define SERF_ERROR_DECOMPRESSION_FAILED (APR_OS_START_USERERR + \ - SERF_ERROR_RANGE + 4) +#define SERF_ERROR_DECOMPRESSION_FAILED (SERF_ERROR_START + 4) /* This code is for when a response received from a http server is not in * http-compliant syntax. */ -#define SERF_ERROR_BAD_HTTP_RESPONSE (APR_OS_START_USERERR + \ - SERF_ERROR_RANGE + 5) +#define SERF_ERROR_BAD_HTTP_RESPONSE (SERF_ERROR_START + 5) +/* The server sent less data than what was announced. */ +#define SERF_ERROR_TRUNCATED_HTTP_RESPONSE (SERF_ERROR_START + 6) +/* The proxy server returned an error while setting up the SSL tunnel. */ +#define SERF_ERROR_SSLTUNNEL_SETUP_FAILED (SERF_ERROR_START + 7) +/* The server unexpectedly closed the connection prematurely. */ +#define SERF_ERROR_ABORTED_CONNECTION (SERF_ERROR_START + 8) + +/* SSL certificates related errors */ +#define SERF_ERROR_SSL_CERT_FAILED (SERF_ERROR_START + 70) + +/* SSL communications related errors */ +#define SERF_ERROR_SSL_COMM_FAILED (SERF_ERROR_START + 71) /* General authentication related errors */ -#define SERF_ERROR_AUTHN_FAILED (APR_OS_START_USERERR + SERF_ERROR_RANGE + 90) +#define SERF_ERROR_AUTHN_FAILED (SERF_ERROR_START + 90) /* None of the available authn mechanisms for the request are supported */ -#define SERF_ERROR_AUTHN_NOT_SUPPORTED (APR_OS_START_USERERR + SERF_ERROR_RANGE + 91) +#define SERF_ERROR_AUTHN_NOT_SUPPORTED (SERF_ERROR_START + 91) /* Authn was requested by the server but the header lacked some attribute */ -#define SERF_ERROR_AUTHN_MISSING_ATTRIBUTE (APR_OS_START_USERERR + SERF_ERROR_RANGE + 92) +#define SERF_ERROR_AUTHN_MISSING_ATTRIBUTE (SERF_ERROR_START + 92) /* Authentication handler initialization related errors */ -#define SERF_ERROR_AUTHN_INITALIZATION_FAILED (APR_OS_START_USERERR +\ - SERF_ERROR_RANGE + 93) +#define SERF_ERROR_AUTHN_INITALIZATION_FAILED (SERF_ERROR_START + 93) + +/* Error code reserved for use in the test suite. */ +#define SERF_ERROR_ISSUE_IN_TESTSUITE (SERF_ERROR_START + 99) /* This macro groups errors potentially raised when reading a http response. */ #define SERF_BAD_RESPONSE_ERROR(status) ((status) \ && ((SERF_ERROR_DECOMPRESSION_FAILED == (status)) \ - ||(SERF_ERROR_BAD_HTTP_RESPONSE == (status)))) + ||(SERF_ERROR_BAD_HTTP_RESPONSE == (status)) \ + ||(SERF_ERROR_TRUNCATED_HTTP_RESPONSE == (status)))) /** * Return a string that describes the specified error code. @@ -366,9 +380,10 @@ /** * Create a new connection associated with the @a ctx serf context. * - * A connection will be created to (eventually) connect to the address - * specified by @a address. The address must live at least as long as - * @a pool (thus, as long as the connection object). + * If no proxy server is configured, a connection will be created to + * (eventually) connect to the address specified by @a address. The address must + * live at least as long as @a pool (thus, as long as the connection object). + * If a proxy server is configured, @address will be ignored. * * The connection object will be allocated within @a pool. Clearing or * destroying this pool will close the connection, and terminate any @@ -480,6 +495,8 @@ * connection @a conn. Setting max_requests to 0 means unlimited (the default). * Ex.: setting max_requests to 1 means a request is sent when a response on the * previous request was received and handled. + * + * In general, serf tends to take around 16KB per outstanding request. */ void serf_connection_set_max_outstanding_requests( serf_connection_t *conn, @@ -556,6 +573,20 @@ serf_request_setup_t setup, void *setup_baton); + +/** Returns detected network latency for the @a conn connection. Negative + * value means that latency is unknwon. + */ +apr_interval_time_t serf_connection_get_latency(serf_connection_t *conn); + +/** Check if a @a request has been completely written. + * + * Returns APR_SUCCESS if the request was written completely on the connection. + * Returns APR_EBUSY if the request is not yet or partially written. + */ +apr_status_t serf_request_is_written( + serf_request_t *request); + /** * Cancel the request specified by the @a request object. * @@ -1030,8 +1061,8 @@ /* Version info */ #define SERF_MAJOR_VERSION 1 -#define SERF_MINOR_VERSION 1 -#define SERF_PATCH_VERSION 0 +#define SERF_MINOR_VERSION 3 +#define SERF_PATCH_VERSION 3 /* Version number string */ #define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \ diff -Nru serf-1.1.0/serf.mak serf-1.3.3/serf.mak --- serf-1.1.0/serf.mak 2011-06-24 19:57:51.000000000 +0000 +++ serf-1.3.3/serf.mak 1970-01-01 00:00:00.000000000 +0000 @@ -1,213 +0,0 @@ -#**** serf Win32 -*- Makefile -*- ******************************************** -# -# Define DEBUG_BUILD to create a debug version of the library. - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF - -CFLAGS = /Zi /W3 /EHsc /I "./" - -!IF "$(DEBUG_BUILD)" == "" -INTDIR = Release -CFLAGS = /MD /O2 /D "NDEBUG" $(CFLAGS) -STATIC_LIB = $(INTDIR)\serf-1.lib -!ELSE -INTDIR = Debug -CFLAGS = /MDd /Od /W3 /Gm /D "_DEBUG" $(CFLAGS) -STATIC_LIB = $(INTDIR)\serf-1.lib -!ENDIF - -######## -# Support for OpenSSL integration -!IF "$(OPENSSL_SRC)" == "" -!ERROR OpenSSL is required. Please define OPENSSL_SRC. -!ELSE -OPENSSL_FLAGS = /I "$(OPENSSL_SRC)\inc32" -!ENDIF - -!IF "$(HTTPD_SRC)" != "" -!IF "$(APR_SRC)" == "" -APR_SRC=$(HTTPD_SRC)\srclib\apr -!ENDIF - -!IF "$(APRUTIL_SRC)" == "" -APRUTIL_SRC=$(HTTPD_SRC)\srclib\apr-util -!ENDIF - -!ENDIF - -######## -# APR -!IF "$(APR_SRC)" == "" -!ERROR APR is required. Please define APR_SRC or HTTPD_SRC. -!ENDIF - -APR_FLAGS = /I "$(APR_SRC)\include" -!IF [IF EXIST "$(APR_SRC)\$(INTDIR)\libapr-1.lib" exit 1] == 1 -APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr-1.lib" -!ELSE -APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr.lib" -!ENDIF - -######## -# APR Util -!IF "$(APRUTIL_SRC)" == "" -!ERROR APR-Util is required. Please define APRUTIL_SRC or HTTPD_SRC. -!ENDIF - -APRUTIL_FLAGS = /I "$(APRUTIL_SRC)\include" -!IF [IF EXIST "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib" exit 1] == 1 -APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib" -!ELSE -APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil.lib" -!ENDIF - -######## -# Support for zlib integration -!IF "$(ZLIB_SRC)" == "" -!ERROR ZLib is required. Please define ZLIB_SRC. -!ELSE -ZLIB_FLAGS = /I "$(ZLIB_SRC)" -!IF "$(ZLIB_DLL)" == "" -!IF "$(ZLIB_LIBDIR)" == "" -!IF "$(DEBUG_BUILD)" == "" -ZLIB_LIBS = "$(ZLIB_SRC)\zlibstat.lib" -!ELSE -ZLIB_LIBS = "$(ZLIB_SRC)\zlibstatD.lib" -!ENDIF -!ELSE -ZLIB_LIBS = "$(ZLIB_LIBDIR)\x86\ZlibStat$(INTDIR)\zlibstat.lib" -ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_WINAPI -!ENDIF -!ELSE -ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_DLL -ZLIB_LIBS = "$(ZLIB_SRC)\zlibdll.lib" -!ENDIF -!ENDIF - - -# Exclude stuff we don't need from the Win32 headers -WIN32_DEFS = /D WIN32 /D WIN32_LEAN_AND_MEAN /D NOUSER /D NOGDI /D NONLS /D NOCRYPT /D SERF_HAVE_SSPI - -CPP=cl.exe -CPP_PROJ = /c /nologo $(CFLAGS) $(WIN32_DEFS) $(APR_FLAGS) $(APRUTIL_FLAGS) $(OPENSSL_FLAGS) $(ZLIB_FLAGS) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" -LIB32=link.exe -LIB32_FLAGS=/nologo - -LIB32_OBJS= \ - "$(INTDIR)\aggregate_buckets.obj" \ - "$(INTDIR)\auth.obj" \ - "$(INTDIR)\auth_basic.obj" \ - "$(INTDIR)\auth_digest.obj" \ - "$(INTDIR)\auth_kerb.obj" \ - "$(INTDIR)\auth_kerb_gss.obj" \ - "$(INTDIR)\auth_kerb_sspi.obj" \ - "$(INTDIR)\context.obj" \ - "$(INTDIR)\ssltunnel.obj" \ - "$(INTDIR)\allocator.obj" \ - "$(INTDIR)\barrier_buckets.obj" \ - "$(INTDIR)\buckets.obj" \ - "$(INTDIR)\chunk_buckets.obj" \ - "$(INTDIR)\dechunk_buckets.obj" \ - "$(INTDIR)\deflate_buckets.obj" \ - "$(INTDIR)\file_buckets.obj" \ - "$(INTDIR)\headers_buckets.obj" \ - "$(INTDIR)\incoming.obj" \ - "$(INTDIR)\iovec_buckets.obj" \ - "$(INTDIR)\limit_buckets.obj" \ - "$(INTDIR)\mmap_buckets.obj" \ - "$(INTDIR)\outgoing.obj" \ - "$(INTDIR)\request_buckets.obj" \ - "$(INTDIR)\response_buckets.obj" \ - "$(INTDIR)\simple_buckets.obj" \ - "$(INTDIR)\socket_buckets.obj" \ - "$(INTDIR)\ssl_buckets.obj" \ - -!IFDEF OPENSSL_STATIC -LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32\libeay32.lib" \ - "$(OPENSSL_SRC)\out32\ssleay32.lib" -!ELSE -LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32dll\libeay32.lib" \ - "$(OPENSSL_SRC)\out32dll\ssleay32.lib" -!ENDIF - -LIB32_OBJS = $(LIB32_OBJS) $(APR_LIBS) $(APRUTIL_LIBS) $(ZLIB_LIBS) - -SYS_LIBS = secur32.lib - -TEST_OBJS = \ - "$(INTDIR)\CuTest.obj" \ - "$(INTDIR)\test_all.obj" \ - "$(INTDIR)\test_util.obj" \ - "$(INTDIR)\test_context.obj" \ - "$(INTDIR)\test_buckets.obj" \ - "$(INTDIR)\test_ssl.obj" \ - "$(INTDIR)\test_server.obj" \ - -TEST_LIBS = user32.lib advapi32.lib gdi32.lib ws2_32.lib - - -ALL: INTDIR $(STATIC_LIB) TESTS - -CLEAN: - -@erase /q "$(INTDIR)" >nul - -INTDIR: - -@if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" - -TESTS: $(STATIC_LIB) $(INTDIR)\serf_response.exe $(INTDIR)\serf_get.exe \ - $(INTDIR)\serf_request.exe $(INTDIR)\test_all.exe - -CHECK: INTDIR TESTS - $(INTDIR)\serf_response.exe test\testcases\simple.response - $(INTDIR)\serf_response.exe test\testcases\chunked-empty.response - $(INTDIR)\serf_response.exe test\testcases\chunked.response - $(INTDIR)\serf_response.exe test\testcases\chunked-trailers.response - $(INTDIR)\serf_response.exe test\testcases\deflate.response - $(INTDIR)\test_all.exe - -"$(STATIC_LIB)": INTDIR $(LIB32_OBJS) - $(LIB32) -lib @<< - $(LIB32_FLAGS) $(LIB32_OBJS) $(SYS_LIBS) /OUT:$@ -<< - - -.c{$(INTDIR)}.obj: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -{auth}.c{$(INTDIR)}.obj: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -{buckets}.c{$(INTDIR)}.obj: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -{test}.c{$(INTDIR)}.obj: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -{test\server}.c{$(INTDIR)}.obj: - $(CPP) @<< - $(CPP_PROJ) $< -<< - -$(INTDIR)\serf_response.exe: $(INTDIR)\serf_response.obj $(STATIC_LIB) - $(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS) - -$(INTDIR)\serf_get.exe: $(INTDIR)\serf_get.obj $(STATIC_LIB) - $(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS) - -$(INTDIR)\serf_request.exe: $(INTDIR)\serf_request.obj $(STATIC_LIB) - $(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS) - -$(INTDIR)\test_all.exe: $(TEST_OBJS) $(STATIC_LIB) - $(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS) diff -Nru serf-1.1.0/serf.pc.in serf-1.3.3/serf.pc.in --- serf-1.1.0/serf.pc.in 2011-07-13 01:10:50.000000000 +0000 +++ serf-1.3.3/serf.pc.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -SERF_MAJOR_VERSION=@SERF_MAJOR_VERSION@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: serf -Description: HTTP client library -Version: @SERF_DOTTED_VERSION@ -Requires.private: libssl libcrypto -Libs: -L${libdir} -lserf-${SERF_MAJOR_VERSION} -Libs.private: @EXTRA_LIBS@ @SERF_LIBS@ -lz -Cflags: -I${includedir} diff -Nru serf-1.1.0/serf_bucket_types.h serf-1.3.3/serf_bucket_types.h --- serf-1.1.0/serf_bucket_types.h 2012-04-19 21:43:22.000000000 +0000 +++ serf-1.3.3/serf_bucket_types.h 2013-07-02 05:31:53.000000000 +0000 @@ -85,6 +85,8 @@ #define SERF_HTTP_VERSION(major, minor) ((major) * 1000 + (minor)) #define SERF_HTTP_11 SERF_HTTP_VERSION(1, 1) #define SERF_HTTP_10 SERF_HTTP_VERSION(1, 0) +#define SERF_HTTP_VERSION_MAJOR(shv) ((int)shv / 1000) +#define SERF_HTTP_VERSION_MINOR(shv) ((int)shv % 1000) typedef struct { int version; @@ -129,6 +131,16 @@ /* ==================================================================== */ +extern const serf_bucket_type_t serf_bucket_type_response_body; +#define SERF_BUCKET_IS_RESPONSE_BODY(b) SERF_BUCKET_CHECK((b), response_body) + +serf_bucket_t *serf_bucket_response_body_create( + serf_bucket_t *stream, + apr_uint64_t limit, + serf_bucket_alloc_t *allocator); + +/* ==================================================================== */ + extern const serf_bucket_type_t serf_bucket_type_bwtp_frame; #define SERF_BUCKET_IS_BWTP_FRAME(b) SERF_BUCKET_CHECK((b), bwtp_frame) @@ -295,6 +307,16 @@ apr_size_t len, serf_bucket_alloc_t *allocator); +/** + * Equivalent to serf_bucket_simple_create, except that the bucket assumes + * responsibility for freeing the data on this allocator without making + * a copy. It is assumed that data was created by a call from allocator. + */ +serf_bucket_t *serf_bucket_simple_own_create( + const char *data, + apr_size_t len, + serf_bucket_alloc_t *allocator); + #define SERF_BUCKET_SIMPLE_STRING(s,a) \ serf_bucket_simple_create(s, strlen(s), NULL, NULL, a); @@ -471,6 +493,7 @@ #define SERF_SSL_CERT_UNKNOWNCA 4 #define SERF_SSL_CERT_SELF_SIGNED 8 #define SERF_SSL_CERT_UNKNOWN_FAILURE 16 +#define SERF_SSL_CERT_REVOKED 32 extern const serf_bucket_type_t serf_bucket_type_ssl_encrypt; #define SERF_BUCKET_IS_SSL_ENCRYPT(b) SERF_BUCKET_CHECK((b), ssl_encrypt) @@ -566,7 +589,7 @@ /** * Extract the fields of the certificate in a table with keys (sha1, notBefore, - * notAfter). The returned table will be allocated in @a pool. + * notAfter, subjectAltName). The returned table will be allocated in @a pool. */ apr_hash_t *serf_ssl_cert_certificate( const serf_ssl_certificate_t *cert, @@ -599,6 +622,15 @@ serf_ssl_context_t *ssl_ctx, serf_ssl_certificate_t *cert); +/** + * Enable or disable SSL compression on a SSL session. + * @a enabled = 1 to enable compression, 0 to disable compression. + * Default = disabled. + */ +apr_status_t serf_ssl_use_compression( + serf_ssl_context_t *ssl_ctx, + int enabled); + serf_bucket_t *serf_bucket_ssl_encrypt_create( serf_bucket_t *stream, serf_ssl_context_t *ssl_context, diff -Nru serf-1.1.0/serf_bucket_util.h serf-1.3.3/serf_bucket_util.h --- serf-1.1.0/serf_bucket_util.h 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/serf_bucket_util.h 2013-02-25 07:13:11.000000000 +0000 @@ -148,6 +148,14 @@ serf_bucket_alloc_t *allocator, const char *str); +/** + * Analogous to apr_pstrcatv, using a bucket allocator instead. + */ +char * serf_bstrcatv( + serf_bucket_alloc_t *allocator, + struct iovec *vec, + int vecs, + apr_size_t *bytes_written); /** * Read data up to a newline. diff -Nru serf-1.1.0/serf_private.h serf-1.3.3/serf_private.h --- serf-1.1.0/serf_private.h 2011-06-16 07:56:09.000000000 +0000 +++ serf-1.3.3/serf_private.h 2013-09-29 06:37:46.000000000 +0000 @@ -23,13 +23,44 @@ /* Windows does not define IOV_MAX, so we need to ensure it is defined. */ #ifndef IOV_MAX -#define IOV_MAX 16 +/* There is no limit for iovec count on Windows, but apr_socket_sendv + allocates WSABUF structures on stack if vecs_count <= 50. */ +#define IOV_MAX 50 +#endif + +/* Older versions of APR do not have this macro. */ +#ifdef APR_SIZE_MAX +#define REQUESTED_MAX APR_SIZE_MAX +#else +#define REQUESTED_MAX (~((apr_size_t)0)) #endif #define SERF_IO_CLIENT (1) #define SERF_IO_CONN (2) #define SERF_IO_LISTENER (3) +/* Internal logging facilities, set flag to 1 to enable console logging for + the selected component. */ +#define SSL_VERBOSE 0 +#define SSL_MSG_VERBOSE 0 /* logs decrypted requests and responses. */ +#define SOCK_VERBOSE 0 +#define SOCK_MSG_VERBOSE 0 /* logs bytes received from or written to a socket. */ +#define CONN_VERBOSE 0 +#define AUTH_VERBOSE 0 + +/* Older versions of APR do not have the APR_VERSION_AT_LEAST macro. Those + implementations are safe. + + If the macro *is* defined, and we're on WIN32, and APR is version 1.4.0+, + then we have a broken WSAPoll() implementation. + + See serf_context_create_ex() below. */ +#if defined(APR_VERSION_AT_LEAST) && defined(WIN32) +#if APR_VERSION_AT_LEAST(1,4,0) +#define BROKEN_WSAPOLL +#endif +#endif + typedef struct serf__authn_scheme_t serf__authn_scheme_t; typedef struct serf_io_baton_t { @@ -64,8 +95,17 @@ serf_bucket_t *resp_bkt; - int written; + int writing_started; int priority; + /* 1 if this is a request to setup a SSL tunnel, 0 for normal requests. */ + int ssltunnel; + + /* This baton is currently only used for digest authentication, which + needs access to the uri of the request in the response handler. + If serf_request_t is replaced by a serf_http_request_t in the future, + which knows about uri and method and such, this baton won't be needed + anymore. */ + void *auth_baton; struct serf_request_t *next; }; @@ -76,11 +116,11 @@ } serf_pollset_t; typedef struct serf__authn_info_t { - const char *realm; - const serf__authn_scheme_t *scheme; void *baton; + + int failed_authn_types; } serf__authn_info_t; struct serf_context_t { @@ -107,8 +147,15 @@ apr_off_t progress_read; apr_off_t progress_written; - /* authentication info for this context, shared by all connections. */ - serf__authn_info_t authn_info; + /* authentication info for the servers used in this context. Shared by all + connections to the same server. + Structure of the hashtable: key: host url, e.g. https://localhost:80 + value: serf__authn_info_t * + */ + apr_hash_t *server_authn_info; + + /* authentication info for the proxy configured in this context, shared by + all connections. */ serf__authn_info_t proxy_authn_info; /* List of authn types supported by the client.*/ @@ -141,7 +188,7 @@ SERF_CONN_INIT, /* no socket created yet */ SERF_CONN_SETUP_SSLTUNNEL, /* ssl tunnel being setup, no requests sent */ SERF_CONN_CONNECTED, /* conn is ready to send requests */ - SERF_CONN_CLOSING, /* conn is closing, no more requests, + SERF_CONN_CLOSING /* conn is closing, no more requests, start a new socket */ } serf__connection_state_t; @@ -203,12 +250,6 @@ serf_request_t *requests; serf_request_t *requests_tail; - /* The list of requests we're holding on to because we're going to - * reset the connection soon. - */ - serf_request_t *hold_requests; - serf_request_t *hold_requests_tail; - struct iovec vec[IOV_MAX]; int vec_len; @@ -221,17 +262,44 @@ unsigned int max_outstanding_requests; int hit_eof; - /* Host info. */ + + /* Host url, path ommitted, syntax: https://svn.apache.org . */ const char *host_url; + + /* Exploded host url, path ommitted. Only scheme, hostinfo, hostname & + port values are filled in. */ apr_uri_t host_info; /* connection and authentication scheme specific information */ void *authn_baton; void *proxy_authn_baton; + + /* Time marker when connection begins. */ + apr_time_t connect_time; + + /* Calculated connection latency. Negative value if latency is unknown. */ + apr_interval_time_t latency; + + /* Needs to read first before we can write again. */ + int stop_writing; }; +/*** Internal bucket functions ***/ + +/** Transform a response_bucket in-place into an aggregate bucket. Restore the + status line and all headers, not just the body. + + This can only be used when we haven't started reading the body of the + response yet. + + Keep internal for now, probably only useful within serf. + */ +apr_status_t serf_response_full_become_aggregate(serf_bucket_t *bucket); + /*** Authentication handler declarations ***/ +typedef enum { PROXY, HOST } peer_t; + /** * For each authentication scheme we need a handler function of type * serf__auth_handler_func_t. This function will be called when an @@ -262,7 +330,8 @@ * connection is opened. */ typedef apr_status_t -(*serf__init_conn_func_t)(int code, +(*serf__init_conn_func_t)(const serf__authn_scheme_t *scheme, + int code, serf_connection_t *conn, apr_pool_t *pool); @@ -273,8 +342,10 @@ * authentication headers (if needed). */ typedef apr_status_t -(*serf__setup_request_func_t)(int code, +(*serf__setup_request_func_t)(peer_t peer, + int code, serf_connection_t *conn, + serf_request_t *request, const char *method, const char *uri, serf_bucket_t *hdrs_bkt); @@ -285,7 +356,9 @@ * (if needed). */ typedef apr_status_t -(*serf__validate_response_func_t)(int code, +(*serf__validate_response_func_t)(const serf__authn_scheme_t *scheme, + peer_t peer, + int code, serf_connection_t *conn, serf_request_t *request, serf_bucket_t *response, @@ -295,15 +368,14 @@ * serf__authn_scheme_t: vtable for an authn scheme provider. */ struct serf__authn_scheme_t { - /* The http status code that's handled by this authentication scheme. - Normal values are 401 for server authentication and 407 for proxy - authentication */ - int code; - - /* The name of this authentication scheme. This should be a case - sensitive match of the string sent in the HTTP authentication header. */ + /* The name of this authentication scheme. Used in headers of requests and + for logging. */ const char *name; + /* Key is the name of the authentication scheme in lower case, to + facilitate case insensitive matching of the response headers. */ + const char *key; + /* Internal code used for this authn type. */ int type; @@ -333,6 +405,14 @@ void *baton, apr_pool_t *pool); +/* Get the cached serf__authn_info_t object for the target server, or create one + when this is the first connection to the server. + TODO: The serf__authn_info_t objects are allocated in the context pool, so + a context that's used to connect to many different servers using Basic or + Digest authencation will hold on to many objects indefinitely. We should be + able to cleanup stale objects from time to time. */ +serf__authn_info_t *serf__get_authn_info_for_server(serf_connection_t *conn); + /* fromt context.c */ void serf__context_progress_delta(void *progress_baton, apr_off_t read, apr_off_t written); @@ -346,8 +426,35 @@ apr_status_t serf__process_connection(serf_connection_t *conn, apr_int16_t events); apr_status_t serf__conn_update_pollset(serf_connection_t *conn); +serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn, + serf_request_setup_t setup, + void *setup_baton); +apr_status_t serf__provide_credentials(serf_context_t *ctx, + char **username, + char **password, + serf_request_t *request, + void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool); /* from ssltunnel.c */ apr_status_t serf__ssltunnel_connect(serf_connection_t *conn); + +/** Logging functions. Use one of the [COMP]_VERBOSE flags to enable specific + logging. + **/ + +/* Logs a standard event, with filename & timestamp header */ +void serf__log(int verbose_flag, const char *filename, const char *fmt, ...); + +/* Logs a standard event, but without prefix. This is useful to build up + log lines in parts. */ +void serf__log_nopref(int verbose_flag, const char *fmt, ...); + +/* Logs a socket event, add local and remote ip address:port */ +void serf__log_skt(int verbose_flag, const char *filename, apr_socket_t *skt, + const char *fmt, ...); + #endif diff -Nru serf-1.1.0/serfmake serf-1.3.3/serfmake --- serf-1.1.0/serfmake 2011-07-13 22:42:17.000000000 +0000 +++ serf-1.3.3/serfmake 1970-01-01 00:00:00.000000000 +0000 @@ -1,485 +0,0 @@ -#!/usr/bin/env python - -import os -import re -import shutil -import sys -import stat -import copy - -### use get_version() ? -MAJOR = 1 - -# Basic defines for our outputs. -LIBNAME = 'libserf-%d' % (MAJOR,) -INCLUDES = 'serf-%d' % (MAJOR,) -PCFILE = 'serf-%d' % (MAJOR,) - - -FILES_HDR = [ - ('.', 'serf'), - ('.', 'serf_bucket_types'), - ('.', 'serf_bucket_util'), - ] - -LIB_FILES = [ - ('.', 'context'), - ('.', 'incoming'), - ('.', 'outgoing'), - ('.', 'ssltunnel'), - - ('buckets', 'aggregate_buckets'), - ('buckets', 'request_buckets'), - ('buckets', 'buckets'), - ('buckets', 'simple_buckets'), - ('buckets', 'file_buckets'), - ('buckets', 'mmap_buckets'), - ('buckets', 'socket_buckets'), - ('buckets', 'response_buckets'), - ('buckets', 'headers_buckets'), - ('buckets', 'allocator'), - ('buckets', 'dechunk_buckets'), - ('buckets', 'deflate_buckets'), - ('buckets', 'limit_buckets'), - ('buckets', 'ssl_buckets'), - ('buckets', 'barrier_buckets'), - ('buckets', 'chunk_buckets'), - ('buckets', 'iovec_buckets'), - ('auth', 'auth'), - ('auth', 'auth_basic'), - ('auth', 'auth_digest'), - ('auth', 'auth_kerb'), - ('auth', 'auth_kerb_gss'), - ] - -TEST_DEPS = [ - ('test', 'CuTest'), - ('test', 'test_util'), - ('test', 'test_context'), - ('test', 'test_buckets'), - ('test', 'test_ssl'), - ('test/server', 'test_server'), - ] - -TEST_HDR_FILES = [ - ('test', 'CuTest'), - ('test', 'test_serf'), - ] - -TEST_FILES = [ - ('test', 'serf_get'), - ('test', 'serf_response'), - ('test', 'serf_request'), - ('test', 'serf_spider'), - ('test', 'test_all'), - ] - -TESTCASES = [ - ('test/testcases', 'simple.response'), - ('test/testcases', 'chunked-empty.response'), - ('test/testcases', 'chunked.response'), - ('test/testcases', 'chunked-trailers.response'), - ('test/testcases', 'deflate.response'), - ] - - -def main(argv): - params = {} - - commands = [] - - for arg in argv[1:]: - idx = arg.find('=') - if idx > 0: - start = arg.rfind('-', 0, idx) - if start > 0: - params[arg[start+1:idx]] = arg[idx+1:].strip() - else: - func = globals().get('cmd_' + arg) - if func: - commands.append(func) - else: - print('ERROR: unknown argument: ' + arg) - usage() - - if not commands: - usage() - - for func in commands: - try: - func(params) - except: - print('ERROR: exception:') - print(sys.exc_info()[1]) - print("") - usage() - - -def usage(): - ### print something - print('serfmake [cmd] [options]') - print('Commands:') - print('\tbuild\tBuilds (default)') - print('\tcheck\tRuns test cases') - print('\tinstall\tInstalls serf into PREFIX') - print('\tclean\tCleans') - print('Options:') - print('\t--with-apr=PATH\tprefix for installed APR and APR-util') - print('\t\t\t(needs apr-1-config and apu-1-config; will look in PATH)') - print('\t--prefix=PATH\tinstall serf into PATH (default: /usr/local)') - print('Quick guide:') - print('\tserfmake --prefix=/usr/local/serf --with-apr=/usr/local/apr install') - sys.exit(1) - - -def cmd_build(param): - builder = Builder(param) - builder.build_target(File('.', LIBNAME, 'la'), False) - builder.build_target(File('.', PCFILE, 'pc'), False) - - -def cmd_install(param): - builder = Builder(param) - ### should be called .install_all() - builder.install_target(File('.', LIBNAME, 'la'), False) - - -def cmd_check(param): - builder = Builder(param) - for dirpath, fname in TEST_FILES: - builder.build_target(File(dirpath, fname, None), False) - - for dirpath, fname in TESTCASES: - case = os.path.join(dirpath, fname) - print('== Testing %s ==' % case) - result = os.system('%s %s' % (os.path.join('test', 'serf_response'), case)) - if result: - raise TestError("", result) - - # run the test suite based on the CuTest framework - result = os.system(os.path.join('test', 'test_all')) - if result: - raise TestError(case, result) - -def cmd_clean(param): - targets = [File(dirpath, fname, 'o') for dirpath, fname in LIB_FILES] - targets += [File(dirpath, fname, 'lo') for dirpath, fname in LIB_FILES] - targets += [File('.', LIBNAME, 'la'), - File('.', PCFILE, 'pc'), - ] - targets += [File(dirpath, fname, 'o') for dirpath, fname in TEST_FILES] - targets += [File(dirpath, fname, 'lo') for dirpath, fname in TEST_FILES] - targets += [File(dirpath, fname, None) for dirpath, fname in TEST_FILES] - targets += [File(dirpath, fname, 'o') for dirpath, fname in TEST_DEPS] - targets += [File(dirpath, fname, 'lo') for dirpath, fname in TEST_DEPS] - - clean = [file for file in targets if file.mtime] - if clean: - sys.stdout.write('Cleaning %d files... ' % len(clean)) - for i in clean: - if i.mtime: - os.remove(i.fname) - print('done.') - else: - print('Clean.') - - -class Builder(object): - def __init__(self, params): - if 'apr' in params: - self.apr = APRConfig(params['apr']) - self.apu = APUConfig(params['apr']) - else: - self.apr = APRConfig(None) - self.apu = APUConfig(None) - - try: - self.prefix = params['prefix'] - except: - self.prefix = '/usr/local' - - ### no way to tweak these - self.libdir = os.path.join(self.prefix, 'lib') - self.pkgconfigdir = os.path.join(self.prefix, 'lib', 'pkgconfig') - self.includedir = os.path.join(self.prefix, 'include', INCLUDES) - - self.load_vars() - self.load_deps() - - def load_vars(self): - self.CC = self.apr.get_value('CC', '--cc') - self.CFLAGS = self.apr.get_value('CFLAGS', '--cflags') - self.CPPFLAGS = self.apr.get_value('CPPFLAGS', '--cppflags') - self.LIBTOOL = self.apr.get_value('LIBTOOL', '--apr-libtool') - self.LDFLAGS = self.apr.get_value('LDFLAGS', '--ldflags') \ - + ' ' + self.apu.get_value('LDFLAGS', '--ldflags') - - self.INCLUDES = '-I%s -I%s -I%s' % ( - '.', - self.apr.get_value(None, '--includedir'), - self.apu.get_value(None, '--includedir'), - ) - if os.getenv('EXTRA_INCLUDES'): - self.INCLUDES += ' -I' + os.getenv('EXTRA_INCLUDES') - - self.LIBS = self.apu.get_value(None, '--link-libtool') \ - + ' ' + self.apu.get_value(None, '--libs') \ - + ' ' + self.apr.get_value(None, '--link-libtool') \ - + ' ' + self.apr.get_value(None, '--libs') \ - + ' -lz' - self.SSL_LIBS = '-lssl -lcrypto' - - self.MODE = 644 - - def load_deps(self): - self.deps = { } - - hdrs = [File(dirpath, fname, 'h') for dirpath, fname in FILES_HDR] - libfiles = [File(dirpath, fname, 'c') for dirpath, fname in LIB_FILES] - libobjs = [File(dirpath, fname, 'lo') for dirpath, fname in LIB_FILES] - for src, obj in zip(libfiles, libobjs): - self._add_compile(src, obj, hdrs) - - self.hdrs = hdrs - - all_libs = self.LIBS + ' ' + self.SSL_LIBS - - lib = File('.', LIBNAME, 'la') - cmd = '%s --silent --mode=link %s %s -rpath %s -o %s %s %s' % ( - self.LIBTOOL, self.CC, self.LDFLAGS, self.libdir, - lib.fname, ' '.join([l.fname for l in libobjs]), all_libs) - self._add_dep(lib, libobjs, cmd) - - # load the test program dependencies now - testhdrs = copy.deepcopy(hdrs) - testhdrs += [File(dirpath, fname, 'h') for dirpath, fname in TEST_HDR_FILES] - testdeps = [File(dirpath, fname, 'c') for dirpath, fname in TEST_DEPS] - testobjs = [File(dirpath, fname, 'lo') for dirpath, fname in TEST_DEPS] - - for testsrc, testobj in zip(testdeps, testobjs): - self._add_compile(testsrc, testobj, testhdrs) - - for dirpath, fname in TEST_FILES: - src = File(dirpath, fname, 'c') - obj = File(dirpath, fname, 'lo') - prog = File(dirpath, fname, None) - - self._add_compile(src, obj, hdrs) - - # test_all requires extra dependencies - if fname == "test_all": - cmd = '%s --silent --mode=link %s %s -static -o %s %s %s %s' % ( - self.LIBTOOL, self.CC, self.LDFLAGS, - prog.fname, lib.fname, ' '.join([l.fname for l in [obj] + testobjs]), - all_libs) - self._add_dep(prog, [lib, obj] + testobjs, cmd) - else: - cmd = '%s --silent --mode=link %s %s -static -o %s %s %s %s' % ( - self.LIBTOOL, self.CC, self.LDFLAGS, - prog.fname, lib.fname, obj.fname, all_libs) - self._add_dep(prog, [lib, obj], cmd) - - # create 'serf-1.pc' if it doesn't exist. - pcfile = File('.', PCFILE, 'pc') - self._add_dep(pcfile, [], self._write_pcfile) - - def _add_compile(self, src, obj, hdrs): - cmd = '%s --silent --mode=compile %s %s %s %s -c -o %s %s' % ( - self.LIBTOOL, self.CC, self.CFLAGS, self.CPPFLAGS, self.INCLUDES, - obj.fname, src.fname) - self._add_dep(obj, [src] + hdrs, cmd) - - def _add_dep(self, target, deps, cmd): - if target.mtime: - for dep in deps: - if dep in self.deps or (dep.mtime and dep.mtime > target.mtime): - # a dep is newer. this needs to be rebuilt. - break - else: - # this is up to date. don't add it to the deps[] structure. - return - # else non-existent, so it must be rebuilt. - - # Commands that are strings are cmdline invocations. Otherwise, it - # should be a callable. - if isinstance(cmd, str): - cmd = CommandLine(cmd) - - # register the dependency so this will get built - self.deps[target] = deps, cmd - - def _write_pcfile(self): - """Generating serf-1.pc ...""" - - open(PCFILE + '.pc', 'w').write( -"""SERF_MAJOR_VERSION=%d -prefix=%s -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include/%s - -Name: serf -Description: HTTP client library -Version: %s -Requires.private: libssl libcrypto -Libs: -L${libdir} -lserf-${SERF_MAJOR_VERSION} -Libs.private: %s -Cflags: -I${includedir} -""" % (MAJOR, self.prefix, INCLUDES, get_version(), self.LIBS)) - - def build_target(self, target, dry_run): - deps, cmd = self.deps.get(target, (None, None)) - if cmd is None: - # it's already up to date. all done. - return - - for f in deps: - subdep = self.deps.get(f) - if subdep: - self.build_target(f, dry_run) - - # build the target now - print(cmd.__doc__) - if not dry_run: - result = cmd() - if result: - raise BuildError(cmd.__doc__, result) - # FALLTHROUGH - - # it's a dry run. pretend we built the target. - del self.deps[target] - return 0 - - def install_target(self, target, dry_run): - self.build_target(target, dry_run) - - # install the target now - if not dry_run: - - for path in (self.libdir, self.pkgconfigdir, self.includedir): - if not os.path.exists(path): - try: - os.makedirs(path) - except OSError: - raise BuildError('os.makedirs', - 'can not create install directories') - - for f in self.hdrs: - print("Installing: %s" % (os.path.basename(f.fname),)) - shutil.copy(f.fname, self.includedir) - - print("Installing: %s.pc" % (PCFILE,)) - shutil.copy(PCFILE + '.pc', self.pkgconfigdir) - - cmd = '%s --silent --mode=install %s -c -m %d %s %s' % ( - self.LIBTOOL, '/usr/bin/install', self.MODE, target.fname, - self.libdir) - - print("Installing: %s" % (os.path.basename(target.fname),)) - result = os.system(cmd) - if result: - raise BuildError(cmd, result) - # FALLTHROUGH - - return 0 - - -class ConfigScript(object): - script_name = None - locations = [ - '/usr/bin', - '/usr/local/bin', - '/usr/local/apache2/bin', - ] - - def __init__(self, search_dir): - if search_dir: - locations = [search_dir, os.path.join(search_dir, 'bin')] - else: - locations = self.locations - - for dirname in locations: - bin = os.path.join(dirname, self.script_name) - if os.access(bin, os.X_OK): - self.bin = bin - break - else: - raise ConfigScriptNotFound(self.script_name) - - def get_value(self, env_name, switch): - if env_name and os.getenv(env_name): - return os.getenv(env_name) - return os.popen('%s %s' % (self.bin, switch), 'r').read().strip() - - -class APRConfig(ConfigScript): - script_name = 'apr-1-config' - - -class APUConfig(ConfigScript): - script_name = 'apu-1-config' - - -class CommandLine(object): - """Simple helper to invoke a system command when called.""" - - def __init__(self, cmd): - self.cmd = cmd - self.__doc__ = cmd # when we print the execution of this command - - def __call__(self): - return os.system(self.cmd) - - -class File: - def __init__(self, dirpath, fname, ext): - if ext: - self.fname = os.path.join(dirpath, fname + '.' + ext) - else: - self.fname = os.path.join(dirpath, fname) - - try: - s = os.stat(self.fname) - except OSError: - self.mtime = None - else: - self.mtime = s[stat.ST_MTIME] - - def __eq__(self, other): - return self.fname == other.fname - - def __hash__(self): - return hash(self.fname) - - -def get_version(): - match = re.search('SERF_MAJOR_VERSION ([0-9]+).*' - 'SERF_MINOR_VERSION ([0-9]+).*' - 'SERF_PATCH_VERSION ([0-9]+)', - open('serf.h').read(), - re.DOTALL) - major, minor, patch = match.groups() - return '%s.%s.%s' % (major, minor, patch) - - -class BuildError(Exception): - "An error occurred while building a target." -class TestError(Exception): - "An error occurred while running a unit test." -class ConfigScriptNotFound(Exception): - def __init__(self, value): - self.value = "ERROR: A configuration script was not found: " + value - def __str__(self): - return self.value - - -if __name__ == '__main__': - main(sys.argv) - - -### -### TODO: -### * obey DESTDIR -### * arfrever says LDFLAGS is passed twice -### * be able to specify libdir and includedir -### diff -Nru serf-1.1.0/ssltunnel.c serf-1.3.3/ssltunnel.c --- serf-1.1.0/ssltunnel.c 2011-06-21 03:28:28.000000000 +0000 +++ serf-1.3.3/ssltunnel.c 2013-07-04 19:58:40.000000000 +0000 @@ -91,21 +91,30 @@ return status; } - /* Body is supposed to be empty. */ - if (sl.code == 200) { + /* RFC 2817: Any successful (2xx) response to a CONNECT request indicates + that the proxy has established a connection to the requested host and + port, and has switched to tunneling the current connection to that server + connection. + */ + if (sl.code >= 200 && sl.code < 300) { request->conn->state = SERF_CONN_CONNECTED; + /* Body is supposed to be empty. */ apr_pool_destroy(ctx->pool); serf_bucket_destroy(request->conn->ssltunnel_ostream); request->conn->stream = NULL; ctx = NULL; + serf__log(CONN_VERBOSE, __FILE__, + "successfully set up ssl tunnel on connection 0x%x\n", + request->conn); + return APR_EOF; } - /* Authentication failure and 200 Ok are handled at this point, + /* Authentication failure and 2xx Ok are handled at this point, the rest are errors. */ - return APR_EGENERAL; /* TODO: better error code */ + return SERF_ERROR_SSLTUNNEL_SETUP_FAILED; } /* Prepare the CONNECT request. */ @@ -150,19 +159,20 @@ ctx = apr_palloc(ssltunnel_pool, sizeof(*ctx)); ctx->pool = ssltunnel_pool; - ctx->uri = apr_psprintf(ctx->pool, "%s:%d", conn->host_info.hostinfo, + ctx->uri = apr_psprintf(ctx->pool, "%s:%d", conn->host_info.hostname, conn->host_info.port); conn->ssltunnel_ostream = serf__bucket_stream_create(conn->allocator, detect_eof, conn); - /* TODO: should be the first request on the connection. */ - serf_connection_priority_request_create(conn, - setup_request, - ctx); + serf__ssltunnel_request_create(conn, + setup_request, + ctx); conn->state = SERF_CONN_SETUP_SSLTUNNEL; + serf__log(CONN_VERBOSE, __FILE__, + "setting up ssl tunnel on connection 0x%x\n", conn); return APR_SUCCESS; } diff -Nru serf-1.1.0/test/CuTest.c serf-1.3.3/test/CuTest.c --- serf-1.1.0/test/CuTest.c 2008-05-06 03:02:12.000000000 +0000 +++ serf-1.3.3/test/CuTest.c 2013-10-04 13:14:19.000000000 +0000 @@ -23,10 +23,7 @@ * * Originally obtained from "http://cutest.sourceforge.net/" version 1.4. * - * Modified for serf as follows - * 1) added CuStringFree(), CuTestFree(), CuSuiteFree(), and - * CuSuiteFreeDeep() - * 0) reformatted the whitespace (doh!) + * See CuTest.h for a list of serf-specific modifications. */ #include #include @@ -146,6 +143,9 @@ t->message = NULL; t->function = function; t->jumpBuf = NULL; + t->setup = NULL; + t->teardown = NULL; + t->testBaton = NULL; } CuTest* CuTestNew(const char* name, TestFunction function) @@ -165,11 +165,16 @@ { jmp_buf buf; tc->jumpBuf = &buf; + if (tc->setup) + tc->testBaton = tc->setup(tc); if (setjmp(buf) == 0) { tc->ran = 1; (tc->function)(tc); } + if (tc->teardown) + tc->teardown(tc->testBaton); + tc->jumpBuf = 0; } @@ -205,6 +210,33 @@ CuFail_Line(tc, file, line, NULL, message); } +void CuAssertStrnEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + const char* expected, size_t explen, + const char* actual) +{ + CuString string; + if ((explen == 0) || + (expected == NULL && actual == NULL) || + (expected != NULL && actual != NULL && + strncmp(expected, actual, explen) == 0)) + { + return; + } + + CuStringInit(&string); + if (message != NULL) + { + CuStringAppend(&string, message); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, "expected <"); + CuStringAppend(&string, expected); + CuStringAppend(&string, "> but was <"); + CuStringAppend(&string, actual); + CuStringAppend(&string, ">"); + CuFailInternal(tc, file, line, &string); +} + void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual) { @@ -227,8 +259,7 @@ CuStringAppend(&string, "> but was <"); CuStringAppend(&string, actual); CuStringAppend(&string, ">"); - CuFailInternal(tc, file, line, &string); -} + CuFailInternal(tc, file, line, &string);} void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual) @@ -266,6 +297,8 @@ { testSuite->count = 0; testSuite->failCount = 0; + testSuite->setup = NULL; + testSuite->teardown = NULL; } CuSuite* CuSuiteNew(void) @@ -296,6 +329,13 @@ assert(testSuite->count < MAX_TEST_CASES); testSuite->list[testSuite->count] = testCase; testSuite->count++; + + /* CuSuiteAdd is called twice per test, don't reset the callbacks if + already set. */ + if (!testCase->setup) + testCase->setup = testSuite->setup; + if (!testCase->teardown) + testCase->teardown = testSuite->teardown; } void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) @@ -365,3 +405,10 @@ CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); } } + +void CuSuiteSetSetupTeardownCallbacks(CuSuite* testSuite, TestCallback setup, + TestCallback teardown) +{ + testSuite->setup = setup; + testSuite->teardown = teardown; +} \ No newline at end of file diff -Nru serf-1.1.0/test/CuTest.h serf-1.3.3/test/CuTest.h --- serf-1.1.0/test/CuTest.h 2008-05-06 03:02:12.000000000 +0000 +++ serf-1.3.3/test/CuTest.h 2013-07-21 14:21:27.000000000 +0000 @@ -24,6 +24,10 @@ * Originally obtained from "http://cutest.sourceforge.net/" version 1.4. * * Modified for serf as follows + * 4) added CuSuiteSetSetupTeardownCallbacks to set a constructor and + * destructor per test suite, run for each test. + * 3) added CuAssertStrnEquals(), CuAssertStrnEquals_Msg() and + * CuAssertStrnEquals_LineMsg() * 2) removed const from struct CuTest.name * 1) added CuStringFree(), CuTestFree(), CuSuiteFree(), and * CuSuiteFreeDeep() @@ -69,6 +73,8 @@ typedef void (*TestFunction)(CuTest *); +typedef void *(*TestCallback)(void *baton); + struct CuTest { char* name; @@ -77,6 +83,10 @@ int ran; const char* message; jmp_buf *jumpBuf; + + TestCallback setup; + TestCallback teardown; + void *testBaton; }; void CuTestInit(CuTest* t, const char* name, TestFunction function); @@ -90,6 +100,9 @@ void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual); +void CuAssertStrnEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + const char* expected, size_t explen, const char* actual); void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual); @@ -108,6 +121,8 @@ #define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertStrnEquals(tc,ex,exlen,ac) CuAssertStrnEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(exlen),(ac)) +#define CuAssertStrnEquals_Msg(tc,ms,ex,exlen,ac) CuAssertStrnEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(exlen),(ac)) #define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) @@ -130,6 +145,9 @@ CuTest* list[MAX_TEST_CASES]; int failCount; + TestCallback setup; + TestCallback teardown; + void *testBaton; } CuSuite; @@ -143,4 +161,7 @@ void CuSuiteSummary(CuSuite* testSuite, CuString* summary); void CuSuiteDetails(CuSuite* testSuite, CuString* details); +void CuSuiteSetSetupTeardownCallbacks(CuSuite* testSuite, TestCallback setup, + TestCallback teardown); + #endif /* CU_TEST_H */ diff -Nru serf-1.1.0/test/mock_buckets.c serf-1.3.3/test/mock_buckets.c --- serf-1.1.0/test/mock_buckets.c 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/mock_buckets.c 2013-06-09 08:32:50.000000000 +0000 @@ -0,0 +1,334 @@ +/* Copyright 2013 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "serf.h" +#include "serf_bucket_util.h" +#include "test_serf.h" + +/* This bucket uses a list of count - data/len - status actions (provided by the + test case), to control the read / read_iovec operations. */ +typedef struct { + mockbkt_action *actions; + int len; + const char *current_data; + int remaining_data; + int current_action; + int remaining_times; +} mockbkt_context_t; + +serf_bucket_t *serf_bucket_mock_create(mockbkt_action *actions, + int len, + serf_bucket_alloc_t *allocator) +{ + mockbkt_context_t *ctx; + + ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); + ctx->actions = actions; + ctx->len = len; + ctx->current_data = 0l; + ctx->remaining_data = -1; + ctx->current_action = 0; + ctx->remaining_times = -1; + + return serf_bucket_create(&serf_bucket_type_mock, allocator, ctx); +} + +static apr_status_t next_action(mockbkt_context_t *ctx) +{ + mockbkt_action *action; + + while (1) + { + if (ctx->current_action >= ctx->len) + return APR_EOF; + + action = &ctx->actions[ctx->current_action]; + + if (ctx->remaining_times == 0) { + ctx->current_action++; + ctx->remaining_times = -1; + ctx->remaining_data = -1; + continue; + } + + if (ctx->remaining_data <= 0) { + ctx->current_data = action->data; + ctx->remaining_times = action->times; + ctx->remaining_data = strlen(action->data); + } + + return APR_SUCCESS; + } +} + +static apr_status_t serf_mock_readline(serf_bucket_t *bucket, + int acceptable, int *found, + const char **data, apr_size_t *len) +{ + mockbkt_context_t *ctx = bucket->data; + mockbkt_action *action; + apr_status_t status; + const char *start_line; + + status = next_action(ctx); + if (status) { + *len = 0; + return status; + } + + action = &ctx->actions[ctx->current_action]; + start_line = *data = ctx->current_data; + *len = ctx->remaining_data; + + serf_util_readline(&start_line, len, acceptable, found); + + /* See how much ctx->current moved forward. */ + *len = start_line - ctx->current_data; + ctx->remaining_data -= *len; + ctx->current_data += *len; + if (ctx->remaining_data == 0) + ctx->remaining_times--; + + return ctx->remaining_data ? APR_SUCCESS : action->status; +} + +static apr_status_t serf_mock_read(serf_bucket_t *bucket, + apr_size_t requested, + const char **data, apr_size_t *len) +{ + mockbkt_context_t *ctx = bucket->data; + mockbkt_action *action; + apr_status_t status; + + status = next_action(ctx); + if (status) { + *len = 0; + return status; + } + + action = &ctx->actions[ctx->current_action]; + *len = requested < ctx->remaining_data ? requested : ctx->remaining_data; + *data = ctx->current_data; + + ctx->remaining_data -= *len; + ctx->current_data += *len; + + if (ctx->remaining_data == 0) + ctx->remaining_times--; + + return ctx->remaining_data ? APR_SUCCESS : action->status; +} + +static apr_status_t serf_mock_peek(serf_bucket_t *bucket, + const char **data, + apr_size_t *len) +{ + mockbkt_context_t *ctx = bucket->data; + mockbkt_action *action; + apr_status_t status; + + status = next_action(ctx); + if (status) + return status; + + action = &ctx->actions[ctx->current_action]; + *len = ctx->remaining_data; + *data = ctx->current_data; + + /* peek only returns an error, APR_EOF or APR_SUCCESS. + APR_EAGAIN is returned as APR_SUCCESS. */ + if (SERF_BUCKET_READ_ERROR(action->status)) + return status; + + return action->status == APR_EOF ? APR_EOF : APR_SUCCESS; +} + +/* An action { "", 0, APR_EAGAIN } means that serf should exit serf_context_run + and pass the buck back to the application. As long as no new data arrives, + this action remains active. + + This function allows the 'application' to trigger the arrival of more data. + If the current action is { "", 0, APR_EAGAIN }, reduce the number of times + the action should run by one, and proceed with the next action if needed. + */ +apr_status_t serf_bucket_mock_more_data_arrived(serf_bucket_t *bucket) +{ + mockbkt_context_t *ctx = bucket->data; + mockbkt_action *action; + apr_status_t status; + + status = next_action(ctx); + if (status) + return status; + + action = &ctx->actions[ctx->current_action]; + if (ctx->remaining_data == 0 && action->status == APR_EAGAIN) { + ctx->remaining_times--; + action->times--; + } + + return APR_SUCCESS; +} + +const serf_bucket_type_t serf_bucket_type_mock = { + "MOCK", + serf_mock_read, + serf_mock_readline, + serf_default_read_iovec, + serf_default_read_for_sendfile, + serf_default_read_bucket, + serf_mock_peek, + serf_default_destroy_and_data, +}; + + +/* internal test for the mock buckets */ +static void test_basic_mock_bucket(CuTest *tc) +{ + serf_bucket_t *mock_bkt; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + /* read one line */ + { + mockbkt_action actions[]= { + { 1, "HTTP/1.1 200 OK" CRLF, APR_EOF }, + }; + mock_bkt = serf_bucket_mock_create(actions, 1, alloc); + read_and_check_bucket(tc, mock_bkt, + "HTTP/1.1 200 OK" CRLF); + + mock_bkt = serf_bucket_mock_create(actions, 1, alloc); + readlines_and_check_bucket(tc, mock_bkt, SERF_NEWLINE_CRLF, + "HTTP/1.1 200 OK" CRLF, 1); + } + /* read one line, character per character */ + { + apr_status_t status; + const char *expected = "HTTP/1.1 200 OK" CRLF; + mockbkt_action actions[]= { + { 1, "HTTP/1.1 200 OK" CRLF, APR_EOF }, + }; + mock_bkt = serf_bucket_mock_create(actions, 1, alloc); + do + { + const char *data; + apr_size_t len; + + status = serf_bucket_read(mock_bkt, 1, &data, &len); + CuAssert(tc, "Got error during bucket reading.", + !SERF_BUCKET_READ_ERROR(status)); + CuAssert(tc, "Read more data than expected.", + strlen(expected) >= len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp(expected, data, len) == 0); + CuAssert(tc, "Read more data than requested.", + len <= 1); + + expected += len; + } while(!APR_STATUS_IS_EOF(status)); + + CuAssert(tc, "Read less data than expected.", strlen(expected) == 0); + } + /* read multiple lines */ + { + mockbkt_action actions[]= { + { 1, "HTTP/1.1 200 OK" CRLF, APR_SUCCESS }, + { 1, "Content-Type: text/plain" CRLF, APR_EOF }, + }; + mock_bkt = serf_bucket_mock_create(actions, 2, alloc); + readlines_and_check_bucket(tc, mock_bkt, SERF_NEWLINE_CRLF, + "HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF, 2); + } + /* read empty line */ + { + mockbkt_action actions[]= { + { 1, "HTTP/1.1 200 OK" CRLF, APR_SUCCESS }, + { 1, "", APR_EAGAIN }, + { 1, "Content-Type: text/plain" CRLF, APR_EOF }, + }; + mock_bkt = serf_bucket_mock_create(actions, 3, alloc); + read_and_check_bucket(tc, mock_bkt, + "HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF); + mock_bkt = serf_bucket_mock_create(actions, 3, alloc); + readlines_and_check_bucket(tc, mock_bkt, SERF_NEWLINE_CRLF, + "HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF, 2); + } + /* read empty line */ + { + mockbkt_action actions[]= { + { 1, "HTTP/1.1 200 OK" CR, APR_SUCCESS }, + { 1, "", APR_EAGAIN }, + { 1, LF, APR_EOF }, + }; + mock_bkt = serf_bucket_mock_create(actions, + sizeof(actions)/sizeof(actions[0]), + alloc); + read_and_check_bucket(tc, mock_bkt, + "HTTP/1.1 200 OK" CRLF); + + mock_bkt = serf_bucket_mock_create(actions, + sizeof(actions)/sizeof(actions[0]), + alloc); + readlines_and_check_bucket(tc, mock_bkt, SERF_NEWLINE_CRLF, + "HTTP/1.1 200 OK" CRLF, 1); + } + /* test more_data_arrived */ + { + apr_status_t status; + const char *data; + apr_size_t len; + int i; + + mockbkt_action actions[]= { + { 1, "", APR_EAGAIN }, + { 1, "blabla", APR_EOF }, + }; + mock_bkt = serf_bucket_mock_create(actions, + sizeof(actions)/sizeof(actions[0]), + alloc); + + for (i = 0; i < 5; i++) { + status = serf_bucket_peek(mock_bkt, &data, &len); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertIntEquals(tc, 0, len); + CuAssertIntEquals(tc, '\0', *data); + } + + serf_bucket_mock_more_data_arrived(mock_bkt); + + status = serf_bucket_peek(mock_bkt, &data, &len); + CuAssertIntEquals(tc, APR_EOF, status); + CuAssertIntEquals(tc, 6, len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp("blabla", data, len) == 0); + } +} + +CuSuite *test_mock_bucket(void) +{ + CuSuite *suite = CuSuiteNew(); + + CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown); + + SUITE_ADD_TEST(suite, test_basic_mock_bucket); + + return suite; +} diff -Nru serf-1.1.0/test/serf_get.c serf-1.3.3/test/serf_get.c --- serf-1.1.0/test/serf_get.c 2012-04-19 21:43:22.000000000 +0000 +++ serf-1.3.3/test/serf_get.c 2013-09-29 06:22:07.000000000 +0000 @@ -25,9 +25,13 @@ #include "serf.h" +/* Add Connection: close header to each request. */ +/* #define CONNECTION_CLOSE_HDR */ + typedef struct { const char *hostinfo; int using_ssl; + int head_request; serf_ssl_context_t *ssl_ctx; serf_bucket_alloc_t *bkt_alloc; } app_baton_t; @@ -37,6 +41,10 @@ apr_status_t why, apr_pool_t *pool) { + app_baton_t *ctx = closed_baton; + + ctx->ssl_ctx = NULL; + if (why) { abort(); } @@ -62,12 +70,24 @@ static apr_status_t ignore_all_cert_errors(void *data, int failures, const serf_ssl_certificate_t *cert) { - print_ssl_cert_errors(failures); + print_ssl_cert_errors(failures); /* In a real application, you would normally would not want to do this */ return APR_SUCCESS; } +static char * +convert_organisation_to_str(apr_hash_t *org, apr_pool_t *pool) +{ + return apr_psprintf(pool, "%s, %s, %s, %s, %s (%s)", + (char*)apr_hash_get(org, "OU", APR_HASH_KEY_STRING), + (char*)apr_hash_get(org, "O", APR_HASH_KEY_STRING), + (char*)apr_hash_get(org, "L", APR_HASH_KEY_STRING), + (char*)apr_hash_get(org, "ST", APR_HASH_KEY_STRING), + (char*)apr_hash_get(org, "C", APR_HASH_KEY_STRING), + (char*)apr_hash_get(org, "E", APR_HASH_KEY_STRING)); +} + static apr_status_t print_certs(void *data, int failures, int error_depth, const serf_ssl_certificate_t * const * certs, apr_size_t certs_len) @@ -86,12 +106,38 @@ fprintf(stderr, "Chain provided with depth=%d\n", error_depth); while ((current = *certs) != NULL) - { + { + apr_hash_t *issuer, *subject, *serf_cert; + apr_array_header_t *san; + + subject = serf_ssl_cert_subject(current, pool); + issuer = serf_ssl_cert_issuer(current, pool); + serf_cert = serf_ssl_cert_certificate(current, pool); + fprintf(stderr, "\n-----BEGIN CERTIFICATE-----\n"); + fprintf(stderr, "Hostname: %s\n", + (const char *)apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)); + fprintf(stderr, "Sha1: %s\n", + (const char *)apr_hash_get(serf_cert, "sha1", APR_HASH_KEY_STRING)); + fprintf(stderr, "Valid from: %s\n", + (const char *)apr_hash_get(serf_cert, "notBefore", APR_HASH_KEY_STRING)); + fprintf(stderr, "Valid until: %s\n", + (const char *)apr_hash_get(serf_cert, "notAfter", APR_HASH_KEY_STRING)); + fprintf(stderr, "Issuer: %s\n", convert_organisation_to_str(issuer, pool)); + + san = apr_hash_get(serf_cert, "subjectAltName", APR_HASH_KEY_STRING); + if (san) { + int i; + for (i = 0; i < san->nelts; i++) { + char *s = APR_ARRAY_IDX(san, i, char*); + fprintf(stderr, "SubjectAltName: %s\n", s); + } + } + fprintf(stderr, "%s\n", serf_ssl_cert_export(current, pool)); fprintf(stderr, "-----END CERTIFICATE-----\n"); ++certs; - } + } apr_pool_destroy(pool); return APR_SUCCESS; @@ -132,7 +178,9 @@ apr_pool_t *pool) { serf_bucket_t *c; + serf_bucket_t *response; serf_bucket_alloc_t *bkt_alloc; + app_baton_t *app_ctx = acceptor_baton; /* get the per-request bucket allocator */ bkt_alloc = serf_request_get_alloc(request); @@ -140,7 +188,12 @@ /* Create a barrier so the response doesn't eat us! */ c = serf_bucket_barrier_create(stream, bkt_alloc); - return serf_bucket_response_create(c, bkt_alloc); + response = serf_bucket_response_create(c, bkt_alloc); + + if (app_ctx->head_request) + serf_bucket_response_set_head(response); + + return response; } typedef struct { @@ -150,6 +203,7 @@ apr_atomic_t completed_requests; #endif int print_headers; + apr_file_t *output_file; serf_response_acceptor_t acceptor; app_baton_t *acceptor_baton; @@ -160,7 +214,10 @@ const char *method; const char *path; const char *req_body_path; - const char *authn; + const char *username; + const char *password; + int auth_attempts; + serf_bucket_t *req_hdrs; } handler_baton_t; /* Kludges for APR 0.9 support. */ @@ -170,33 +227,111 @@ #define apr_atomic_read32 apr_atomic_read #endif + +static int append_request_headers(void *baton, + const char *key, + const char *value) +{ + serf_bucket_t *hdrs_bkt = baton; + serf_bucket_headers_setc(hdrs_bkt, key, value); + return 0; +} + +static apr_status_t setup_request(serf_request_t *request, + void *setup_baton, + serf_bucket_t **req_bkt, + serf_response_acceptor_t *acceptor, + void **acceptor_baton, + serf_response_handler_t *handler, + void **handler_baton, + apr_pool_t *pool) +{ + handler_baton_t *ctx = setup_baton; + serf_bucket_t *hdrs_bkt; + serf_bucket_t *body_bkt; + + if (ctx->req_body_path) { + apr_file_t *file; + apr_status_t status; + + status = apr_file_open(&file, ctx->req_body_path, APR_READ, + APR_OS_DEFAULT, pool); + + if (status) { + printf("Error opening file (%s)\n", ctx->req_body_path); + return status; + } + + body_bkt = serf_bucket_file_create(file, + serf_request_get_alloc(request)); + } + else { + body_bkt = NULL; + } + + *req_bkt = serf_request_bucket_request_create(request, ctx->method, + ctx->path, body_bkt, + serf_request_get_alloc(request)); + + hdrs_bkt = serf_bucket_request_get_headers(*req_bkt); + + serf_bucket_headers_setn(hdrs_bkt, "User-Agent", + "Serf/" SERF_VERSION_STRING); + /* Shouldn't serf do this for us? */ + serf_bucket_headers_setn(hdrs_bkt, "Accept-Encoding", "gzip"); +#ifdef CONNECTION_CLOSE_HDR + serf_bucket_headers_setn(hdrs_bkt, "Connection", "close"); +#endif + + /* Add the extra headers from the command line */ + if (ctx->req_hdrs != NULL) { + serf_bucket_headers_do(ctx->req_hdrs, append_request_headers, hdrs_bkt); + } + + *acceptor = ctx->acceptor; + *acceptor_baton = ctx->acceptor_baton; + *handler = ctx->handler; + *handler_baton = ctx; + + return APR_SUCCESS; +} + static apr_status_t handle_response(serf_request_t *request, serf_bucket_t *response, void *handler_baton, apr_pool_t *pool) { - const char *data; - apr_size_t len; serf_status_line sl; apr_status_t status; handler_baton_t *ctx = handler_baton; if (!response) { - /* A NULL response can come back if the request failed completely */ - return APR_EGENERAL; + /* A NULL response probably means that the connection was closed while + this request was already written. Just requeue it. */ + serf_connection_t *conn = serf_request_get_conn(request); + + serf_connection_request_create(conn, setup_request, handler_baton); + return APR_SUCCESS; } + status = serf_bucket_response_status(response, &sl); if (status) { return status; } while (1) { - status = serf_bucket_read(response, 2048, &data, &len); + struct iovec vecs[64]; + int vecs_read; + apr_size_t bytes_written; + + status = serf_bucket_read_iovec(response, 8000, 64, vecs, &vecs_read); if (SERF_BUCKET_READ_ERROR(status)) return status; /* got some data. print it out. */ - fwrite(data, 1, len, stdout); + if (vecs_read) { + apr_file_writev(ctx->output_file, vecs, vecs_read, &bytes_written); + } /* are we done yet? */ if (APR_STATUS_IS_EOF(status)) { @@ -204,11 +339,16 @@ serf_bucket_t *hdrs; hdrs = serf_bucket_response_get_headers(response); while (1) { - status = serf_bucket_read(hdrs, 2048, &data, &len); + status = serf_bucket_read_iovec(hdrs, 8000, 64, vecs, + &vecs_read); + if (SERF_BUCKET_READ_ERROR(status)) return status; - fwrite(data, 1, len, stdout); + if (vecs_read) { + apr_file_writev(ctx->output_file, vecs, vecs_read, + &bytes_written); + } if (APR_STATUS_IS_EOF(status)) { break; } @@ -228,59 +368,28 @@ /* NOTREACHED */ } -static apr_status_t setup_request(serf_request_t *request, - void *setup_baton, - serf_bucket_t **req_bkt, - serf_response_acceptor_t *acceptor, - void **acceptor_baton, - serf_response_handler_t *handler, - void **handler_baton, - apr_pool_t *pool) +static apr_status_t +credentials_callback(char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) { - handler_baton_t *ctx = setup_baton; - serf_bucket_t *hdrs_bkt; - serf_bucket_t *body_bkt; - - if (ctx->req_body_path) { - apr_file_t *file; - apr_status_t status; - - status = apr_file_open(&file, ctx->req_body_path, APR_READ, - APR_OS_DEFAULT, pool); + handler_baton_t *ctx = baton; - if (status) { - printf("Error opening file (%s)\n", ctx->req_body_path); - return status; - } - - body_bkt = serf_bucket_file_create(file, - serf_request_get_alloc(request)); - } - else { - body_bkt = NULL; + if (ctx->auth_attempts > 0) + { + return SERF_ERROR_AUTHN_FAILED; } + else + { + *username = (char*)ctx->username; + *password = (char*)ctx->password; + ctx->auth_attempts++; - *req_bkt = serf_request_bucket_request_create(request, ctx->method, - ctx->path, body_bkt, - serf_request_get_alloc(request)); - - hdrs_bkt = serf_bucket_request_get_headers(*req_bkt); - - serf_bucket_headers_setn(hdrs_bkt, "User-Agent", - "Serf/" SERF_VERSION_STRING); - /* Shouldn't serf do this for us? */ - serf_bucket_headers_setn(hdrs_bkt, "Accept-Encoding", "gzip"); - - if (ctx->authn != NULL) { - serf_bucket_headers_setn(hdrs_bkt, "Authorization", ctx->authn); + return APR_SUCCESS; } - - *acceptor = ctx->acceptor; - *acceptor_baton = ctx->acceptor_baton; - *handler = ctx->handler; - *handler_baton = ctx; - - return APR_SUCCESS; } static void print_usage(apr_pool_t *pool) @@ -290,28 +399,34 @@ puts("-v\tDisplay version"); puts("-H\tPrint response headers"); puts("-n Fetch URL times"); - puts("-a Present Basic authentication credentials"); + puts("-x Number of maximum outstanding requests inflight"); + puts("-U Username for Basic/Digest authentication"); + puts("-P Password for Basic/Digest authentication"); puts("-m Use the HTTP Method"); puts("-f Use the as the request body"); puts("-p Use the as proxy server"); + puts("-r Use as request header"); } int main(int argc, const char **argv) { apr_status_t status; apr_pool_t *pool; + serf_bucket_alloc_t *bkt_alloc; serf_context_t *context; serf_connection_t *connection; serf_request_t *request; app_baton_t app_ctx; handler_baton_t handler_ctx; + serf_bucket_t *req_hdrs = NULL; apr_uri_t url; const char *proxy = NULL; const char *raw_url, *method, *req_body_path = NULL; - int count; + int count, inflight; int i; int print_headers; - char *authn = NULL; + const char *username = NULL; + const char *password = ""; apr_getopt_t *opt; char opt_c; const char *opt_arg; @@ -321,9 +436,11 @@ apr_pool_create(&pool, NULL); /* serf_initialize(); */ + bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL); - /* Default to one round of fetching. */ + /* Default to one round of fetching with no limit to max inflight reqs. */ count = 1; + inflight = 0; /* Default to GET. */ method = "GET"; /* Do not print headers by default. */ @@ -331,17 +448,15 @@ apr_getopt_init(&opt, pool, argc, argv); - while ((status = apr_getopt(opt, "a:f:hHm:n:vp:", &opt_c, &opt_arg)) == + while ((status = apr_getopt(opt, "U:P:f:hHm:n:vp:x:r:", &opt_c, &opt_arg)) == APR_SUCCESS) { - int srclen, enclen; switch (opt_c) { - case 'a': - srclen = strlen(opt_arg); - enclen = apr_base64_encode_len(srclen); - authn = apr_palloc(pool, enclen + 6); - strcpy(authn, "Basic "); - (void) apr_base64_encode(&authn[6], opt_arg, srclen); + case 'U': + username = opt_arg; + break; + case 'P': + password = opt_arg; break; case 'f': req_body_path = opt_arg; @@ -365,9 +480,40 @@ return errno; } break; + case 'x': + errno = 0; + inflight = apr_strtoi64(opt_arg, NULL, 10); + if (errno) { + printf("Problem converting number of requests to have outstanding (%d)\n", + errno); + return errno; + } + break; case 'p': proxy = opt_arg; break; + case 'r': + { + char *sep; + char *hdr_val; + + if (req_hdrs == NULL) { + /* first request header, allocate bucket */ + req_hdrs = serf_bucket_headers_create(bkt_alloc); + } + sep = strchr(opt_arg, ':'); + if ((sep == NULL) || (sep == opt_arg) || (strlen(sep) <= 1)) { + printf("Invalid request header string (%s)\n", opt_arg); + return EINVAL; + } + hdr_val = sep + 1; + while (*hdr_val == ' ') { + hdr_val++; + } + serf_bucket_headers_setx(req_hdrs, opt_arg, (sep - opt_arg), 1, + hdr_val, strlen(hdr_val), 1); + } + break; case 'v': puts("Serf version: " SERF_VERSION_STRING); exit(0); @@ -398,6 +544,13 @@ app_ctx.using_ssl = 0; } + if (strcasecmp(method, "HEAD") == 0) { + app_ctx.head_request = 1; + } + else { + app_ctx.head_request = 0; + } + app_ctx.hostinfo = url.hostinfo; context = serf_context_create(pool); @@ -444,8 +597,19 @@ serf_config_proxy(context, proxy_address); } + if (username) + { + serf_config_authn_types(context, SERF_AUTHN_ALL); + } + else + { + serf_config_authn_types(context, SERF_AUTHN_NTLM | SERF_AUTHN_NEGOTIATE); + } + + serf_config_credentials_callback(context, credentials_callback); + /* ### Connection or Context should have an allocator? */ - app_ctx.bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL); + app_ctx.bkt_alloc = bkt_alloc; app_ctx.ssl_ctx = NULL; status = serf_connection_create2(&connection, context, url, @@ -460,17 +624,27 @@ handler_ctx.completed_requests = 0; handler_ctx.print_headers = print_headers; + apr_file_open_stdout(&handler_ctx.output_file, pool); handler_ctx.host = url.hostinfo; handler_ctx.method = method; - handler_ctx.path = url.path; - handler_ctx.authn = authn; + handler_ctx.path = apr_pstrcat(pool, + url.path, + url.query ? "?" : "", + url.query ? url.query : "", + NULL); + handler_ctx.username = username; + handler_ctx.password = password; + handler_ctx.auth_attempts = 0; handler_ctx.req_body_path = req_body_path; handler_ctx.acceptor = accept_response; handler_ctx.acceptor_baton = &app_ctx; handler_ctx.handler = handle_response; + handler_ctx.req_hdrs = req_hdrs; + + serf_connection_set_max_outstanding_requests(connection, inflight); for (i = 0; i < count; i++) { request = serf_connection_request_create(connection, setup_request, @@ -483,9 +657,13 @@ continue; if (status) { char buf[200]; + const char *err_string; + err_string = serf_error_string(status); + if (!err_string) { + err_string = apr_strerror(status, buf, sizeof(buf)); + } - printf("Error running context: (%d) %s\n", status, - apr_strerror(status, buf, sizeof(buf))); + printf("Error running context: (%d) %s\n", status, err_string); apr_pool_destroy(pool); exit(1); } diff -Nru serf-1.1.0/test/server/serfcacert.pem serf-1.3.3/test/server/serfcacert.pem --- serf-1.1.0/test/server/serfcacert.pem 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/server/serfcacert.pem 2013-04-18 20:00:01.000000000 +0000 @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1048591 (0x10000f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Root CA, CN=Serf Root CA/emailAddress=serfrootca@example.com + Validity + Not Before: Apr 18 19:47:06 2013 GMT + Not After : Apr 18 19:47:06 2014 GMT + Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite CA, CN=Serf CA/emailAddress=serfca@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:bb:2a:03:8e:a3:47:80:8c:c8:f8:b7:1d:4a:3b: + 1f:15:57:52:32:b8:a9:9e:a3:01:ed:0d:88:58:b6: + fa:19:81:92:d1:de:4d:c6:f9:a2:0d:1b:65:68:3a: + 74:32:ae:f3:51:1f:bb:43:fc:27:64:1c:2c:3b:bd: + f5:e8:b1:ef:47:ab:a7:54:1e:d1:5f:49:c9:5f:2f: + a2:78:5e:76:3b:72:9b:c1:e5:33:ce:10:6a:56:cc: + 64:2e:23:22:ef:b7:6a:e0:a8:fc:06:2e:06:ce:56: + b8:8a:de:1b:9b:83:54:6a:9f:c5:16:84:7f:72:f2: + e1:f5:56:51:2d:55:ce:61:dd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + DD:F9:F5:E9:24:D4:B4:59:CA:4C:E9:98:61:1A:5D:8C:69:D1:CF:13 + X509v3 Authority Key Identifier: + keyid:B2:3E:19:35:C1:C4:4F:23:79:ED:BF:E8:DC:5C:31:03:F0:2F:15:77 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 2a:db:bd:2b:da:8b:c3:e6:bb:6c:f0:7f:2e:1a:50:8a:81:49: + 15:45:88:e8:98:6d:0e:ed:67:8d:31:49:b1:71:50:fc:77:c1: + b9:39:0d:9e:23:ef:cb:e5:04:77:59:b4:0b:54:bd:37:8a:50: + 3b:da:0a:b2:30:f0:ee:04:50:67:e1:15:d0:50:53:7b:bd:96: + 7d:05:3a:e1:fd:85:aa:09:b0:7b:bf:e8:a1:ee:6c:68:2c:51: + a4:0c:f3:1d:9c:0e:4f:53:0c:a6:a3:41:53:0c:3d:58:09:14: + 44:5d:dc:cc:ea:85:de:dd:1f:3b:57:65:29:a2:c4:32:87:6b: + e3:a0 +-----BEGIN CERTIFICATE----- +MIIDGDCCAoGgAwIBAgIDEAAPMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJC +RTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVsZW4xHzAdBgNVBAoM +FkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xGzAZBgNVBAsMElRlc3QgU3VpdGUgUm9v +dCBDQTEVMBMGA1UEAwwMU2VyZiBSb290IENBMSUwIwYJKoZIhvcNAQkBFhZzZXJm +cm9vdGNhQGV4YW1wbGUuY29tMB4XDTEzMDQxODE5NDcwNloXDTE0MDQxODE5NDcw +NlowgaAxCzAJBgNVBAYTAkJFMRAwDgYDVQQIDAdBbnR3ZXJwMREwDwYDVQQHDAhN +ZWNoZWxlbjEfMB0GA1UECgwWSW4gU2VyZiB3ZSB0cnVzdCwgSW5jLjEWMBQGA1UE +CwwNVGVzdCBTdWl0ZSBDQTEQMA4GA1UEAwwHU2VyZiBDQTEhMB8GCSqGSIb3DQEJ +ARYSc2VyZmNhQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQC7KgOOo0eAjMj4tx1KOx8VV1IyuKmeowHtDYhYtvoZgZLR3k3G+aING2VoOnQy +rvNRH7tD/CdkHCw7vfXose9Hq6dUHtFfSclfL6J4XnY7cpvB5TPOEGpWzGQuIyLv +t2rgqPwGLgbOVriK3hubg1Rqn8UWhH9y8uH1VlEtVc5h3QIDAQABo1AwTjAdBgNV +HQ4EFgQU3fn16STUtFnKTOmYYRpdjGnRzxMwHwYDVR0jBBgwFoAUsj4ZNcHETyN5 +7b/o3FwxA/AvFXcwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAq270r +2ovD5rts8H8uGlCKgUkVRYjomG0O7WeNMUmxcVD8d8G5OQ2eI+/L5QR3WbQLVL03 +ilA72gqyMPDuBFBn4RXQUFN7vZZ9BTrh/YWqCbB7v+ih7mxoLFGkDPMdnA5PUwym +o0FTDD1YCRREXdzM6oXe3R87V2UposQyh2vjoA== +-----END CERTIFICATE----- Binary files /tmp/FsRqlhrSmI/serf-1.1.0/test/server/serfclientcert.p12 and /tmp/aDQ64Ct_hD/serf-1.3.3/test/server/serfclientcert.p12 differ diff -Nru serf-1.1.0/test/server/serfrootcacert.pem serf-1.3.3/test/server/serfrootcacert.pem --- serf-1.1.0/test/server/serfrootcacert.pem 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/server/serfrootcacert.pem 2013-04-14 21:26:33.000000000 +0000 @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 14060582211199810902 (0xc321390661bdbd56) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Root CA, CN=Serf Root CA/emailAddress=serfrootca@example.com + Validity + Not Before: Apr 13 11:19:14 2013 GMT + Not After : Apr 11 11:19:14 2023 GMT + Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Root CA, CN=Serf Root CA/emailAddress=serfrootca@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:e1:dd:69:ea:ac:fd:f2:73:81:ec:ed:b6:b1:0e: + 70:23:8c:01:6d:ab:f3:43:ab:0f:fc:8a:6a:23:eb: + 6c:48:37:c9:c0:8f:29:61:00:7e:89:1f:00:d1:68: + dd:70:de:bd:34:32:0e:41:ac:f9:ea:c1:a6:0d:b5: + 65:be:5c:9e:f1:b4:27:54:c1:79:61:63:d4:2d:06: + 11:5f:cc:4c:d9:d3:ef:4e:da:9f:a4:26:16:cb:3f: + 86:f8:21:7d:c5:3a:32:34:c8:cb:85:ad:c4:3f:e4: + b3:ad:8e:a7:67:9e:0c:3b:5a:58:29:5f:ce:96:3b: + e3:f5:ca:42:eb:7b:44:d5:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B2:3E:19:35:C1:C4:4F:23:79:ED:BF:E8:DC:5C:31:03:F0:2F:15:77 + X509v3 Authority Key Identifier: + keyid:B2:3E:19:35:C1:C4:4F:23:79:ED:BF:E8:DC:5C:31:03:F0:2F:15:77 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + c3:ec:1f:3e:b1:87:d0:80:10:f9:bf:73:1b:38:d4:b1:b7:80: + 4d:ea:20:c1:79:7d:f5:58:42:11:13:28:ab:b1:b4:0a:88:9c: + 20:4d:9c:b5:5a:41:28:5e:f6:69:5e:55:bb:e2:1a:b9:c6:62: + 38:86:32:7b:93:28:ca:9e:af:d1:06:f9:93:c2:5d:92:c0:25: + 68:6a:e1:fe:85:2a:19:a7:6b:17:4d:23:9a:72:d6:d0:c1:80: + ff:74:10:8b:62:7a:11:c3:9a:87:2a:e4:7d:d1:8c:72:a6:bf: + c1:3b:d8:b8:33:c0:ff:b0:f7:d6:0e:a3:dd:36:fe:8a:41:a0: + 98:cc +-----BEGIN CERTIFICATE----- +MIIDLDCCApWgAwIBAgIJAMMhOQZhvb1WMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJCRTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVsZW4xHzAd +BgNVBAoMFkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xGzAZBgNVBAsMElRlc3QgU3Vp +dGUgUm9vdCBDQTEVMBMGA1UEAwwMU2VyZiBSb290IENBMSUwIwYJKoZIhvcNAQkB +FhZzZXJmcm9vdGNhQGV4YW1wbGUuY29tMB4XDTEzMDQxMzExMTkxNFoXDTIzMDQx +MTExMTkxNFowga4xCzAJBgNVBAYTAkJFMRAwDgYDVQQIDAdBbnR3ZXJwMREwDwYD +VQQHDAhNZWNoZWxlbjEfMB0GA1UECgwWSW4gU2VyZiB3ZSB0cnVzdCwgSW5jLjEb +MBkGA1UECwwSVGVzdCBTdWl0ZSBSb290IENBMRUwEwYDVQQDDAxTZXJmIFJvb3Qg +Q0ExJTAjBgkqhkiG9w0BCQEWFnNlcmZyb290Y2FAZXhhbXBsZS5jb20wgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAOHdaeqs/fJzgezttrEOcCOMAW2r80OrD/yK +aiPrbEg3ycCPKWEAfokfANFo3XDevTQyDkGs+erBpg21Zb5cnvG0J1TBeWFj1C0G +EV/MTNnT707an6QmFss/hvghfcU6MjTIy4WtxD/ks62Op2eeDDtaWClfzpY74/XK +Qut7RNV1AgMBAAGjUDBOMB0GA1UdDgQWBBSyPhk1wcRPI3ntv+jcXDED8C8VdzAf +BgNVHSMEGDAWgBSyPhk1wcRPI3ntv+jcXDED8C8VdzAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4GBAMPsHz6xh9CAEPm/cxs41LG3gE3qIMF5ffVYQhETKKux +tAqInCBNnLVaQShe9mleVbviGrnGYjiGMnuTKMqer9EG+ZPCXZLAJWhq4f6FKhmn +axdNI5py1tDBgP90EItiehHDmocq5H3RjHKmv8E72LgzwP+w99YOo902/opBoJjM +-----END CERTIFICATE----- diff -Nru serf-1.1.0/test/server/serfserver_expired_cert.pem serf-1.3.3/test/server/serfserver_expired_cert.pem --- serf-1.1.0/test/server/serfserver_expired_cert.pem 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/server/serfserver_expired_cert.pem 2013-05-07 10:59:15.000000000 +0000 @@ -0,0 +1,63 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1048596 (0x100014) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite CA, CN=Serf CA/emailAddress=serfca@example.com + Validity + Not Before: Nov 20 12:00:00 2010 GMT + Not After : Nov 20 12:00:00 2012 GMT + Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Server, CN=Serf Server/emailAddress=serfserver@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:ea:92:6f:ab:ed:ce:e1:c3:a8:2e:3e:03:9e:a0: + d8:c0:e4:df:e3:58:1f:bf:eb:18:23:c8:ca:a5:9a: + f0:f2:b5:97:ce:df:47:15:9a:0e:96:41:cc:b9:92: + 66:0c:f0:11:f7:f1:8f:3c:29:48:31:4a:1d:93:db: + 0a:f0:e9:98:5f:98:ed:07:1c:4e:2e:9f:e3:f3:3f: + 2c:2f:20:d8:f1:5e:8a:8f:3a:aa:3e:9c:f5:99:07: + 8c:a6:e9:9c:df:03:59:c1:ff:37:5a:bf:69:e8:41: + bd:c0:28:66:c4:4b:0a:ab:dd:93:a1:8f:3e:5e:34: + 5c:e6:04:6c:1d:8b:a3:88:6b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 18:3A:EE:7E:57:49:42:43:23:42:E4:C9:6B:60:E7:64:1B:08:B2:90 + X509v3 Authority Key Identifier: + keyid:DD:F9:F5:E9:24:D4:B4:59:CA:4C:E9:98:61:1A:5D:8C:69:D1:CF:13 + + Signature Algorithm: sha1WithRSAEncryption + 11:b1:e3:27:7c:1b:3a:6b:c7:2e:e4:8e:ed:d4:d3:49:b5:9c: + 8f:06:08:b7:36:9d:8e:da:02:37:e5:59:5e:6b:e5:67:d0:df: + ec:84:dc:b8:92:c4:e4:07:21:92:ff:76:16:45:07:3b:67:c2: + 27:2f:63:1a:ad:60:24:33:21:a9:9b:4e:f4:9c:8e:17:1b:15: + d3:90:4e:22:f3:84:2f:ec:7c:bd:18:ea:cb:ab:bc:97:10:c9: + 53:f4:76:35:94:af:52:93:6e:ba:2e:2d:e4:3b:12:fb:3f:c2: + 10:b1:dd:59:e2:a3:60:56:a7:02:26:d2:6b:1e:23:33:ba:85: + 5f:9d +-----BEGIN CERTIFICATE----- +MIIDQTCCAqqgAwIBAgIDEAAUMA0GCSqGSIb3DQEBBQUAMIGgMQswCQYDVQQGEwJC +RTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVsZW4xHzAdBgNVBAoM +FkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xFjAUBgNVBAsMDVRlc3QgU3VpdGUgQ0Ex +EDAOBgNVBAMMB1NlcmYgQ0ExITAfBgkqhkiG9w0BCQEWEnNlcmZjYUBleGFtcGxl +LmNvbTAeFw0xMDExMjAxMjAwMDBaFw0xMjExMjAxMjAwMDBaMIGsMQswCQYDVQQG +EwJCRTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVsZW4xHzAdBgNV +BAoMFkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xGjAYBgNVBAsMEVRlc3QgU3VpdGUg +U2VydmVyMRQwEgYDVQQDDAtTZXJmIFNlcnZlcjElMCMGCSqGSIb3DQEJARYWc2Vy +ZnNlcnZlckBleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +6pJvq+3O4cOoLj4DnqDYwOTf41gfv+sYI8jKpZrw8rWXzt9HFZoOlkHMuZJmDPAR +9/GPPClIMUodk9sK8OmYX5jtBxxOLp/j8z8sLyDY8V6KjzqqPpz1mQeMpumc3wNZ +wf83Wr9p6EG9wChmxEsKq92ToY8+XjRc5gRsHYujiGsCAwEAAaN7MHkwCQYDVR0T +BAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNh +dGUwHQYDVR0OBBYEFBg67n5XSUJDI0LkyWtg52QbCLKQMB8GA1UdIwQYMBaAFN35 +9ekk1LRZykzpmGEaXYxp0c8TMA0GCSqGSIb3DQEBBQUAA4GBABGx4yd8Gzprxy7k +ju3U00m1nI8GCLc2nY7aAjflWV5r5WfQ3+yE3LiSxOQHIZL/dhZFBztnwicvYxqt +YCQzIambTvScjhcbFdOQTiLzhC/sfL0Y6survJcQyVP0djWUr1KTbrouLeQ7Evs/ +whCx3Vnio2BWpwIm0mseIzO6hV+d +-----END CERTIFICATE----- diff -Nru serf-1.1.0/test/server/serfserver_future_cert.pem serf-1.3.3/test/server/serfserver_future_cert.pem --- serf-1.1.0/test/server/serfserver_future_cert.pem 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/server/serfserver_future_cert.pem 2013-05-07 10:59:15.000000000 +0000 @@ -0,0 +1,63 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1048597 (0x100015) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite CA, CN=Serf CA/emailAddress=serfca@example.com + Validity + Not Before: Nov 20 12:00:00 2023 GMT + Not After : Nov 20 12:00:00 2025 GMT + Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Server, CN=Serf Server/emailAddress=serfserver@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:ea:92:6f:ab:ed:ce:e1:c3:a8:2e:3e:03:9e:a0: + d8:c0:e4:df:e3:58:1f:bf:eb:18:23:c8:ca:a5:9a: + f0:f2:b5:97:ce:df:47:15:9a:0e:96:41:cc:b9:92: + 66:0c:f0:11:f7:f1:8f:3c:29:48:31:4a:1d:93:db: + 0a:f0:e9:98:5f:98:ed:07:1c:4e:2e:9f:e3:f3:3f: + 2c:2f:20:d8:f1:5e:8a:8f:3a:aa:3e:9c:f5:99:07: + 8c:a6:e9:9c:df:03:59:c1:ff:37:5a:bf:69:e8:41: + bd:c0:28:66:c4:4b:0a:ab:dd:93:a1:8f:3e:5e:34: + 5c:e6:04:6c:1d:8b:a3:88:6b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 18:3A:EE:7E:57:49:42:43:23:42:E4:C9:6B:60:E7:64:1B:08:B2:90 + X509v3 Authority Key Identifier: + keyid:DD:F9:F5:E9:24:D4:B4:59:CA:4C:E9:98:61:1A:5D:8C:69:D1:CF:13 + + Signature Algorithm: sha1WithRSAEncryption + 04:6a:2f:a9:fb:18:69:74:ad:3c:24:19:be:81:7e:03:f0:74: + f0:26:7d:b4:74:2a:8b:d3:a8:b3:33:73:af:35:5a:6c:ea:d8: + e9:0e:45:14:57:19:b4:7a:17:e1:b4:9a:3f:7e:7b:9c:c9:1d: + 5d:1f:47:28:18:4b:a6:81:96:e0:99:ee:44:cf:13:1b:a1:aa: + b6:f0:82:91:09:e7:bd:5f:4e:ae:b3:70:38:e4:93:72:6f:25: + bb:ad:d0:a5:e6:db:85:c8:a7:7b:10:cc:c7:16:bf:8b:c2:f3: + c3:9a:35:d0:dd:66:6d:b3:5b:7c:0c:54:f2:1d:c6:f4:4f:75: + 6e:91 +-----BEGIN CERTIFICATE----- +MIIDQTCCAqqgAwIBAgIDEAAVMA0GCSqGSIb3DQEBBQUAMIGgMQswCQYDVQQGEwJC +RTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVsZW4xHzAdBgNVBAoM +FkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xFjAUBgNVBAsMDVRlc3QgU3VpdGUgQ0Ex +EDAOBgNVBAMMB1NlcmYgQ0ExITAfBgkqhkiG9w0BCQEWEnNlcmZjYUBleGFtcGxl +LmNvbTAeFw0yMzExMjAxMjAwMDBaFw0yNTExMjAxMjAwMDBaMIGsMQswCQYDVQQG +EwJCRTEQMA4GA1UECAwHQW50d2VycDERMA8GA1UEBwwITWVjaGVsZW4xHzAdBgNV +BAoMFkluIFNlcmYgd2UgdHJ1c3QsIEluYy4xGjAYBgNVBAsMEVRlc3QgU3VpdGUg +U2VydmVyMRQwEgYDVQQDDAtTZXJmIFNlcnZlcjElMCMGCSqGSIb3DQEJARYWc2Vy +ZnNlcnZlckBleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +6pJvq+3O4cOoLj4DnqDYwOTf41gfv+sYI8jKpZrw8rWXzt9HFZoOlkHMuZJmDPAR +9/GPPClIMUodk9sK8OmYX5jtBxxOLp/j8z8sLyDY8V6KjzqqPpz1mQeMpumc3wNZ +wf83Wr9p6EG9wChmxEsKq92ToY8+XjRc5gRsHYujiGsCAwEAAaN7MHkwCQYDVR0T +BAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNh +dGUwHQYDVR0OBBYEFBg67n5XSUJDI0LkyWtg52QbCLKQMB8GA1UdIwQYMBaAFN35 +9ekk1LRZykzpmGEaXYxp0c8TMA0GCSqGSIb3DQEBBQUAA4GBAARqL6n7GGl0rTwk +Gb6BfgPwdPAmfbR0KovTqLMzc681Wmzq2OkORRRXGbR6F+G0mj9+e5zJHV0fRygY +S6aBluCZ7kTPExuhqrbwgpEJ571fTq6zcDjkk3JvJbut0KXm24XIp3sQzMcWv4vC +88OaNdDdZm2zW3wMVPIdxvRPdW6R +-----END CERTIFICATE----- diff -Nru serf-1.1.0/test/server/serfservercert.pem serf-1.3.3/test/server/serfservercert.pem --- serf-1.1.0/test/server/serfservercert.pem 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/server/serfservercert.pem 2013-05-17 20:20:35.000000000 +0000 @@ -0,0 +1,50 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 1048599 (0x100017) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite CA, CN=Serf CA/emailAddress=serfca@example.com + Validity + Not Before: May 17 20:09:08 2013 GMT + Not After : May 17 20:09:08 2014 GMT + Subject: C=BE, ST=Antwerp, L=Mechelen, O=In Serf we trust, Inc., OU=Test Suite Server, CN=localhost/emailAddress=serfserver@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:ea:92:6f:ab:ed:ce:e1:c3:a8:2e:3e:03:9e:a0: + d8:c0:e4:df:e3:58:1f:bf:eb:18:23:c8:ca:a5:9a: + f0:f2:b5:97:ce:df:47:15:9a:0e:96:41:cc:b9:92: + 66:0c:f0:11:f7:f1:8f:3c:29:48:31:4a:1d:93:db: + 0a:f0:e9:98:5f:98:ed:07:1c:4e:2e:9f:e3:f3:3f: + 2c:2f:20:d8:f1:5e:8a:8f:3a:aa:3e:9c:f5:99:07: + 8c:a6:e9:9c:df:03:59:c1:ff:37:5a:bf:69:e8:41: + bd:c0:28:66:c4:4b:0a:ab:dd:93:a1:8f:3e:5e:34: + 5c:e6:04:6c:1d:8b:a3:88:6b + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 83:26:09:bf:45:7e:ef:a2:94:97:25:78:a9:2c:c9:2f:fb:53: + 61:8b:9b:72:49:dd:81:19:48:ac:5e:b3:e7:f5:c3:31:a6:8a: + 8b:21:20:fd:bd:89:ff:90:b3:11:6e:99:03:48:a3:33:69:e9: + af:91:d8:40:e0:01:9c:42:5b:71:98:41:0c:03:c1:29:92:8a: + 1b:12:51:d9:b2:7b:63:23:03:8b:63:74:fd:6f:9a:c9:4c:c3: + 95:9a:d3:32:1e:6e:1d:e1:a8:1e:16:ea:ce:28:ca:c1:11:c4: + 26:15:dd:7c:b6:1a:ee:7e:00:db:39:ae:4b:94:bc:27:3a:1e: + 20:8b +-----BEGIN CERTIFICATE----- +MIICvTCCAiYCAxAAFzANBgkqhkiG9w0BAQUFADCBoDELMAkGA1UEBhMCQkUxEDAO +BgNVBAgMB0FudHdlcnAxETAPBgNVBAcMCE1lY2hlbGVuMR8wHQYDVQQKDBZJbiBT +ZXJmIHdlIHRydXN0LCBJbmMuMRYwFAYDVQQLDA1UZXN0IFN1aXRlIENBMRAwDgYD +VQQDDAdTZXJmIENBMSEwHwYJKoZIhvcNAQkBFhJzZXJmY2FAZXhhbXBsZS5jb20w +HhcNMTMwNTE3MjAwOTA4WhcNMTQwNTE3MjAwOTA4WjCBqjELMAkGA1UEBhMCQkUx +EDAOBgNVBAgMB0FudHdlcnAxETAPBgNVBAcMCE1lY2hlbGVuMR8wHQYDVQQKDBZJ +biBTZXJmIHdlIHRydXN0LCBJbmMuMRowGAYDVQQLDBFUZXN0IFN1aXRlIFNlcnZl +cjESMBAGA1UEAwwJbG9jYWxob3N0MSUwIwYJKoZIhvcNAQkBFhZzZXJmc2VydmVy +QGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqkm+r7c7h +w6guPgOeoNjA5N/jWB+/6xgjyMqlmvDytZfO30cVmg6WQcy5kmYM8BH38Y88KUgx +Sh2T2wrw6ZhfmO0HHE4un+PzPywvINjxXoqPOqo+nPWZB4ym6ZzfA1nB/zdav2no +Qb3AKGbESwqr3ZOhjz5eNFzmBGwdi6OIawIDAQABMA0GCSqGSIb3DQEBBQUAA4GB +AIMmCb9Ffu+ilJcleKksyS/7U2GLm3JJ3YEZSKxes+f1wzGmioshIP29if+QsxFu +mQNIozNp6a+R2EDgAZxCW3GYQQwDwSmSihsSUdmye2MjA4tjdP1vmslMw5Wa0zIe +bh3hqB4W6s4oysERxCYV3Xy2Gu5+ANs5rkuUvCc6HiCL +-----END CERTIFICATE----- diff -Nru serf-1.1.0/test/server/serfserverkey.pem serf-1.3.3/test/server/serfserverkey.pem --- serf-1.1.0/test/server/serfserverkey.pem 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/server/serfserverkey.pem 2013-04-18 20:00:01.000000000 +0000 @@ -0,0 +1,17 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIOgdKxeTZjDQCAggA +MBQGCCqGSIb3DQMHBAgCe5obSU/JDwSCAoAY2Pdf7Hq0SD+bPHq21ZvDKnX6oMDC +cgcFlFSdooCY0GQn4IkONWCJWkyYDGQ3DJcNev7ZhQdyC0iuSzYDQAlbxrewB1Kh +Aoo8WP/T2iVb86bLhOg7fu+k++LHtQ1xZm9PdY4DC48lbrpX9N+qhGfPDzoYrZY6 +C7b6aCCZfTPrtykuCO14EATw6EixR597NlDOCfZGiIwc3B0OWmp/wMsFbbVljN+Y +whYjSvulXlN+QGLkBYyQMvAWvOJJjK0jCIKzVu+K5wFHteCOjlTrQ9yxfnyuu5KH +gHF9k/fSlKx52XIiiClpGJ5o98U3jiPgBISEsbY+QZfQrNj90BjVcyv3aj6bmXBc +/rIg6O2gpoXRpy+pnuxHGMYwveVBab3Ul7r9qdaG+tiKcGqmq1hrAdOOpeWODGYg +oUQC/iLGEzdtpkYD1+5uKkv06sZ6mSVpMyyrlEp2GB7Z/9GpDuhtES/CK59qY/yV +rG3VJZ9OVHUun3nyw8AcNAWpaciVXXZk79i0vqDS+XamhyZCTZzeDXuSYUzPRmiQ +UUfzQuAPbLOggqF5AJi8W4xMaT/Z2Kai6h72oXr5xVcVYQK/9kNA3nBBIq5o88LF +PSZCWqZ1kOvwyLMnK8wu0oAiVXmk2VrJwdVuVgs0dxf+QOfx4cExYa1T6bVdXAKj +QaJWfLI6iPosaY6g2YGwho7KIJmAkW6I+aWDJ12TwFWz9874Xis3FAbiNJUzPqVT +wCBPk0Yckio+U49hpFYzADENnRtDrzLfjK1n3gsN8GLfqBL9bNM8bD/XyRFuWTb6 +Kz+/rf3aPmra1Q/YFpvQ66E46ciHzAkeVXMamzaZJ+12EzaBuqb4Eeq9 +-----END ENCRYPTED PRIVATE KEY----- diff -Nru serf-1.1.0/test/server/test_server.c serf-1.3.3/test/server/test_server.c --- serf-1.1.0/test/server/test_server.c 2012-02-15 20:16:09.000000000 +0000 +++ serf-1.3.3/test/server/test_server.c 2013-07-21 14:21:27.000000000 +0000 @@ -20,46 +20,29 @@ #include #include "serf.h" +#include "serf_private.h" /* for serf__log and serf__bucket_stream_create */ #include "test_server.h" -struct serv_ctx_t { - /* Pool for resource allocation. */ - apr_pool_t *pool; - - apr_int32_t options; - - /* Array of actions which server will replay when client connected. */ - test_server_action_t *action_list; - /* Size of action_list array. */ - apr_size_t action_count; - /* Index of current action. */ - apr_size_t cur_action; - - /* Array of messages the server will receive from the client. */ - test_server_message_t *message_list; - /* Size of message_list array. */ - apr_size_t message_count; - /* Index of current message. */ - apr_size_t cur_message; - - /* Number of messages received that the server didn't respond to yet. */ - apr_size_t outstanding_responses; +#define BUFSIZE 8192 - /* Position in message buffer (incoming messages being read). */ - apr_size_t message_buf_pos; +/* Cleanup callback for a server. */ +static apr_status_t cleanup_server(void *baton) +{ + serv_ctx_t *servctx = baton; + apr_status_t status; - /* Position in action buffer. (outgoing messages being sent). */ - apr_size_t action_buf_pos; + if (servctx->serv_sock) + status = apr_socket_close(servctx->serv_sock); + else + status = APR_EGENERAL; - /* Address for server binding. */ - apr_sockaddr_t *serv_addr; - apr_socket_t *serv_sock; - - /* Accepted client socket. NULL if there is no client socket. */ - apr_socket_t *client_sock; + if (servctx->client_sock) { + apr_socket_close(servctx->client_sock); + } -}; + return status; +} /* Replay support functions */ static void next_message(serv_ctx_t *servctx) @@ -73,6 +56,69 @@ servctx->action_buf_pos = 0; } +static apr_status_t +socket_write(serv_ctx_t *serv_ctx, const char *data, + apr_size_t *len) +{ + return apr_socket_send(serv_ctx->client_sock, data, len); +} + +static apr_status_t +socket_read(serv_ctx_t *serv_ctx, char *data, + apr_size_t *len) +{ + return apr_socket_recv(serv_ctx->client_sock, data, len); +} + +static apr_status_t +create_client_socket(apr_socket_t **skt, + serv_ctx_t *servctx, + const char *url) +{ + apr_sockaddr_t *address; + apr_uri_t uri; + apr_status_t status; + + status = apr_uri_parse(servctx->pool, url, &uri); + if (status != APR_SUCCESS) + return status; + + status = apr_sockaddr_info_get(&address, + uri.hostname, + APR_UNSPEC, + uri.port, + 0, + servctx->pool); + if (status != APR_SUCCESS) + return status; + + status = apr_socket_create(skt, + address->family, + SOCK_STREAM, +#if APR_MAJOR_VERSION > 0 + APR_PROTO_TCP, +#endif + servctx->pool); + if (status != APR_SUCCESS) + return status; + + /* Set the socket to be non-blocking */ + status = apr_socket_timeout_set(*skt, 0); + if (status != APR_SUCCESS) + return status; + + status = apr_socket_connect(*skt, address); + if (status != APR_SUCCESS && !APR_STATUS_IS_EINPROGRESS(status)) + return status; + + return APR_SUCCESS; +} + +static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket) +{ + return APR_EAGAIN; +} + /* Verify received requests and take the necessary actions (return a response, kill the connection ...) */ static apr_status_t replay(serv_ctx_t *servctx, @@ -85,34 +131,43 @@ if (rtnevents & APR_POLLIN) { if (servctx->message_list == NULL) { /* we're not expecting any requests to reach this server! */ - printf("Received request where none was expected\n"); + serf__log(TEST_VERBOSE, __FILE__, + "Received request where none was expected.\n"); - return APR_EGENERAL; + return SERF_ERROR_ISSUE_IN_TESTSUITE; } if (servctx->cur_action >= servctx->action_count) { char buf[128]; apr_size_t len = sizeof(buf); - status = apr_socket_recv(servctx->client_sock, buf, &len); + status = servctx->read(servctx, buf, &len); if (! APR_STATUS_IS_EAGAIN(status)) { /* we're out of actions! */ - printf("Received more requests than expected.\n"); + serf__log(TEST_VERBOSE, __FILE__, + "Received more requests than expected.\n"); - return APR_EGENERAL; + return SERF_ERROR_ISSUE_IN_TESTSUITE; } return status; } action = &servctx->action_list[servctx->cur_action]; + serf__log(TEST_VERBOSE, __FILE__, + "POLLIN while replaying action %d, kind: %d.\n", + servctx->cur_action, action->kind); + + /* Read the remaining data from the client and kill the socket. */ if (action->kind == SERVER_IGNORE_AND_KILL_CONNECTION) { char buf[128]; apr_size_t len = sizeof(buf); - status = apr_socket_recv(servctx->client_sock, buf, &len); + status = servctx->read(servctx, buf, &len); if (status == APR_EOF) { + serf__log(TEST_VERBOSE, __FILE__, + "Killing this connection.\n"); apr_socket_close(servctx->client_sock); servctx->client_sock = NULL; next_action(servctx); @@ -131,44 +186,100 @@ message = &servctx->message_list[servctx->cur_message]; msg_len = strlen(message->text); - len = msg_len - servctx->message_buf_pos; - if (len > sizeof(buf)) - len = sizeof(buf); - - status = apr_socket_recv(servctx->client_sock, buf, &len); - if (status != APR_SUCCESS) - return status; - - if (servctx->options & TEST_SERVER_DUMP) - fwrite(buf, len, 1, stdout); - - if (strncmp(buf, message->text + servctx->message_buf_pos, len) != 0) { - /* ## TODO: Better diagnostics. */ - printf("Expected: (\n"); - fwrite(message->text + servctx->message_buf_pos, len, 1, stdout); - printf(")\n"); - printf("Actual: (\n"); - fwrite(buf, len, 1, stdout); - printf(")\n"); - - return APR_EGENERAL; - } - - servctx->message_buf_pos += len; + do + { + len = msg_len - servctx->message_buf_pos; + if (len > sizeof(buf)) + len = sizeof(buf); + + status = servctx->read(servctx, buf, &len); + if (SERF_BUCKET_READ_ERROR(status)) + return status; + + if (status == APR_EOF) { + serf__log(TEST_VERBOSE, __FILE__, + "Server: Client hung up the connection.\n"); + break; + } + if (servctx->options & TEST_SERVER_DUMP) + fwrite(buf, len, 1, stdout); + + if (strncmp(buf, + message->text + servctx->message_buf_pos, + len) != 0) { + /* ## TODO: Better diagnostics. */ + printf("Expected: (\n"); + fwrite(message->text + servctx->message_buf_pos, len, 1, + stdout); + printf(")\n"); + printf("Actual: (\n"); + fwrite(buf, len, 1, stdout); + printf(")\n"); + + return SERF_ERROR_ISSUE_IN_TESTSUITE; + } + + servctx->message_buf_pos += len; + + if (servctx->message_buf_pos >= msg_len) { + next_message(servctx); + servctx->message_buf_pos -= msg_len; + if (action->kind == SERVER_RESPOND) + servctx->outstanding_responses++; + if (action->kind == SERVER_RECV) + next_action(servctx); + break; + } + } while (!status); + } + else if (action->kind == PROXY_FORWARD) { + apr_size_t len; + char buf[BUFSIZE]; + serf_bucket_t *tmp; - if (servctx->message_buf_pos >= msg_len) { - next_message(servctx); - servctx->message_buf_pos -= msg_len; - if (action->kind == SERVER_RESPOND) - servctx->outstanding_responses++; - if (action->kind == SERVER_RECV) + /* Read all incoming data from the client to forward it to the + server later. */ + do + { + len = BUFSIZE; + + status = servctx->read(servctx, buf, &len); + if (SERF_BUCKET_READ_ERROR(status)) + return status; + + serf__log(TEST_VERBOSE, __FILE__, + "proxy: reading %d bytes %.*s from client with " + "status %d.\n", + len, len, buf, status); + + if (status == APR_EOF) { + serf__log(TEST_VERBOSE, __FILE__, + "Proxy: client hung up the connection. Reset the " + "connection to the server.\n"); + /* We have to stop forwarding, if a new connection opens + the CONNECT request should not be forwarded to the + server. */ next_action(servctx); - } + } + if (!servctx->servstream) + servctx->servstream = serf__bucket_stream_create( + servctx->allocator, + detect_eof,servctx); + if (len) { + tmp = serf_bucket_simple_copy_create(buf, len, + servctx->allocator); + serf_bucket_aggregate_append(servctx->servstream, tmp); + } + } while (!status); } } if (rtnevents & APR_POLLOUT) { action = &servctx->action_list[servctx->cur_action]; + serf__log(TEST_VERBOSE, __FILE__, + "POLLOUT when replaying action %d, kind: %d.\n", servctx->cur_action, + action->kind); + if (action->kind == SERVER_RESPOND && servctx->outstanding_responses) { apr_size_t msg_len; apr_size_t len; @@ -176,8 +287,9 @@ msg_len = strlen(action->text); len = msg_len - servctx->action_buf_pos; - status = apr_socket_send(servctx->client_sock, - action->text + servctx->action_buf_pos, &len); + status = servctx->send(servctx, + action->text + servctx->action_buf_pos, + &len); if (status != APR_SUCCESS) return status; @@ -193,10 +305,55 @@ } else if (action->kind == SERVER_KILL_CONNECTION || action->kind == SERVER_IGNORE_AND_KILL_CONNECTION) { + serf__log(TEST_VERBOSE, __FILE__, + "Killing this connection.\n"); apr_socket_close(servctx->client_sock); servctx->client_sock = NULL; next_action(servctx); } + else if (action->kind == PROXY_FORWARD) { + apr_size_t len; + char *buf; + + if (!servctx->proxy_client_sock) { + serf__log(TEST_VERBOSE, __FILE__, "Proxy: setting up connection " + "to server.\n"); + status = create_client_socket(&servctx->proxy_client_sock, + servctx, action->text); + if (!servctx->clientstream) + servctx->clientstream = serf__bucket_stream_create( + servctx->allocator, + detect_eof,servctx); + } + + /* Send all data received from the server to the client. */ + do + { + apr_size_t readlen; + + readlen = BUFSIZE; + + status = serf_bucket_read(servctx->clientstream, readlen, + &buf, &readlen); + if (SERF_BUCKET_READ_ERROR(status)) + return status; + if (!readlen) + break; + + len = readlen; + + serf__log(TEST_VERBOSE, __FILE__, + "proxy: sending %d bytes to client.\n", len); + status = servctx->send(servctx, buf, &len); + if (status != APR_SUCCESS) { + return status; + } + + if (len != readlen) /* abort for now, return buf to aggregate + if not everything could be sent. */ + return APR_EGENERAL; + } while (!status); + } } else if (rtnevents & APR_POLLIN) { /* ignore */ @@ -209,7 +366,87 @@ return status; } -apr_status_t test_server_run(serv_ctx_t *servctx, +/* Exchange data between proxy and server */ +static apr_status_t proxy_replay(serv_ctx_t *servctx, + apr_int16_t rtnevents, + apr_pool_t *pool) +{ + apr_status_t status; + + if (rtnevents & APR_POLLIN) { + apr_size_t len; + char buf[BUFSIZE]; + serf_bucket_t *tmp; + + serf__log(TEST_VERBOSE, __FILE__, "proxy_replay: POLLIN\n"); + /* Read all incoming data from the server to forward it to the + client later. */ + do + { + len = BUFSIZE; + + status = apr_socket_recv(servctx->proxy_client_sock, buf, &len); + if (SERF_BUCKET_READ_ERROR(status)) + return status; + + serf__log(TEST_VERBOSE, __FILE__, + "proxy: reading %d bytes %.*s from server.\n", + len, len, buf); + tmp = serf_bucket_simple_copy_create(buf, len, + servctx->allocator); + serf_bucket_aggregate_append(servctx->clientstream, tmp); + } while (!status); + } + + if (rtnevents & APR_POLLOUT) { + apr_size_t len; + char *buf; + + serf__log(TEST_VERBOSE, __FILE__, "proxy_replay: POLLOUT\n"); + /* Send all data received from the client to the server. */ + do + { + apr_size_t readlen; + + readlen = BUFSIZE; + + if (!servctx->servstream) + servctx->servstream = serf__bucket_stream_create( + servctx->allocator, + detect_eof,servctx); + status = serf_bucket_read(servctx->servstream, BUFSIZE, + &buf, &readlen); + if (SERF_BUCKET_READ_ERROR(status)) + return status; + if (!readlen) + break; + + len = readlen; + + serf__log(TEST_VERBOSE, __FILE__, + "proxy: sending %d bytes %.*s to server.\n", + len, len, buf); + status = apr_socket_send(servctx->proxy_client_sock, buf, &len); + if (status != APR_SUCCESS) { + return status; + } + + if (len != readlen) /* abort for now */ + return APR_EGENERAL; + } while (!status); + } + else if (rtnevents & APR_POLLIN) { + /* ignore */ + } + else { + printf("Unknown rtnevents: %d\n", rtnevents); + abort(); + } + + return status; +} + +apr_status_t run_test_server(serv_ctx_t *servctx, apr_short_interval_time_t duration, apr_pool_t *pool) { @@ -219,24 +456,48 @@ const apr_pollfd_t *desc; /* create a new pollset */ +#ifdef BROKEN_WSAPOLL + status = apr_pollset_create_ex(&pollset, 32, pool, 0, + APR_POLLSET_SELECT); +#else status = apr_pollset_create(&pollset, 32, pool, 0); +#endif + if (status != APR_SUCCESS) return status; /* Don't accept new connection while processing client connection. At least for present time.*/ if (servctx->client_sock) { - apr_pollfd_t pfd = { pool, APR_POLL_SOCKET, APR_POLLIN | APR_POLLOUT, 0, - { NULL }, NULL }; + apr_pollfd_t pfd = { 0 }; + + pfd.desc_type = APR_POLL_SOCKET; pfd.desc.s = servctx->client_sock; + pfd.reqevents = APR_POLLIN | APR_POLLOUT; + status = apr_pollset_add(pollset, &pfd); if (status != APR_SUCCESS) goto cleanup; + + if (servctx->proxy_client_sock) { + apr_pollfd_t pfd = { 0 }; + + pfd.desc_type = APR_POLL_SOCKET; + pfd.desc.s = servctx->proxy_client_sock; + pfd.reqevents = APR_POLLIN | APR_POLLOUT; + + status = apr_pollset_add(pollset, &pfd); + if (status != APR_SUCCESS) + goto cleanup; + } } else { - apr_pollfd_t pfd = { pool, APR_POLL_SOCKET, APR_POLLIN, 0, - { NULL }, NULL }; + apr_pollfd_t pfd = { 0 }; + + pfd.desc_type = APR_POLL_SOCKET; pfd.desc.s = servctx->serv_sock; + pfd.reqevents = APR_POLLIN; + status = apr_pollset_add(pollset, &pfd); if (status != APR_SUCCESS) goto cleanup; @@ -253,6 +514,10 @@ if (status != APR_SUCCESS) goto cleanup; + serf__log_skt(TEST_VERBOSE, __FILE__, servctx->client_sock, + "server/proxy accepted incoming connection.\n"); + + apr_socket_opt_set(servctx->client_sock, APR_SO_NONBLOCK, 1); apr_socket_timeout_set(servctx->client_sock, 0); @@ -261,12 +526,43 @@ } if (desc->desc.s == servctx->client_sock) { + if (servctx->handshake) { + status = servctx->handshake(servctx); + if (status) + goto cleanup; + } + /* Replay data to socket. */ status = replay(servctx, desc->rtnevents, pool); if (APR_STATUS_IS_EOF(status)) { apr_socket_close(servctx->client_sock); servctx->client_sock = NULL; + if (servctx->reset) + servctx->reset(servctx); + + /* If this is a proxy and the client closed the connection, also + close the connection to the server. */ + if (servctx->proxy_client_sock) { + apr_socket_close(servctx->proxy_client_sock); + servctx->proxy_client_sock = NULL; + goto cleanup; + } + } + else if (APR_STATUS_IS_EAGAIN(status)) { + status = APR_SUCCESS; + } + else if (status != APR_SUCCESS) { + /* Real error. */ + goto cleanup; + } + } + if (desc->desc.s == servctx->proxy_client_sock) { + /* Replay data to proxy socket. */ + status = proxy_replay(servctx, desc->rtnevents, pool); + if (APR_STATUS_IS_EOF(status)) { + apr_socket_close(servctx->proxy_client_sock); + servctx->proxy_client_sock = NULL; } else if (APR_STATUS_IS_EAGAIN(status)) { status = APR_SUCCESS; @@ -286,39 +582,62 @@ return status; } -/* Start a TCP server on port SERV_PORT in thread THREAD. srv_replay is a array - of action to replay when connection started. replay_count is count of - actions in srv_replay. */ -apr_status_t test_start_server(serv_ctx_t **servctx_p, - apr_sockaddr_t *address, - test_server_message_t *message_list, - apr_size_t message_count, - test_server_action_t *action_list, - apr_size_t action_count, - apr_int32_t options, - apr_pool_t *pool) + +/* Setup the context needed to start a TCP server on adress. + message_list is a list of expected requests. + action_list is the list of responses to be returned in order. + */ +void setup_test_server(serv_ctx_t **servctx_p, + apr_sockaddr_t *address, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + apr_pool_t *pool) { - apr_status_t status; - apr_socket_t *serv_sock; serv_ctx_t *servctx; servctx = apr_pcalloc(pool, sizeof(*servctx)); + apr_pool_cleanup_register(pool, servctx, + cleanup_server, + apr_pool_cleanup_null); *servctx_p = servctx; servctx->serv_addr = address; servctx->options = options; servctx->pool = pool; + servctx->allocator = serf_bucket_allocator_create(pool, NULL, NULL); servctx->message_list = message_list; servctx->message_count = message_count; servctx->action_list = action_list; servctx->action_count = action_count; + /* Start replay from first action. */ + servctx->cur_action = 0; + servctx->action_buf_pos = 0; + servctx->outstanding_responses = 0; + + servctx->read = socket_read; + servctx->send = socket_write; + + *servctx_p = servctx; +} + +apr_status_t start_test_server(serv_ctx_t *servctx) +{ + apr_status_t status; + apr_socket_t *serv_sock; + /* create server socket */ #if APR_VERSION_AT_LEAST(1, 0, 0) - status = apr_socket_create(&serv_sock, address->family, SOCK_STREAM, 0, - pool); + status = apr_socket_create(&serv_sock, servctx->serv_addr->family, + SOCK_STREAM, 0, + servctx->pool); #else - status = apr_socket_create(&serv_sock, address->family, SOCK_STREAM, pool); + status = apr_socket_create(&serv_sock, servctx->serv_addr->family, + SOCK_STREAM, + servctx->pool); #endif if (status != APR_SUCCESS) @@ -332,28 +651,13 @@ if (status != APR_SUCCESS) return status; - /* Start replay from first action. */ - servctx->cur_action = 0; - servctx->action_buf_pos = 0; - servctx->outstanding_responses = 0; - /* listen for clients */ - apr_socket_listen(serv_sock, SOMAXCONN); + status = apr_socket_listen(serv_sock, SOMAXCONN); if (status != APR_SUCCESS) return status; servctx->serv_sock = serv_sock; servctx->client_sock = NULL; - return APR_SUCCESS; -} - -apr_status_t test_server_destroy(serv_ctx_t *servctx, apr_pool_t *pool) -{ - apr_socket_close(servctx->serv_sock); - - if (servctx->client_sock) { - apr_socket_close(servctx->client_sock); - } return APR_SUCCESS; } diff -Nru serf-1.1.0/test/server/test_server.h serf-1.3.3/test/server/test_server.h --- serf-1.1.0/test/server/test_server.h 2011-06-13 13:45:19.000000000 +0000 +++ serf-1.3.3/test/server/test_server.h 2013-07-21 14:21:27.000000000 +0000 @@ -16,7 +16,9 @@ #ifndef TEST_SERVER_H #define TEST_SERVER_H -typedef struct serv_ctx_t serv_ctx_t; +/* Test logging facilities, set flag to 1 to enable console logging for + the test suite. */ +#define TEST_VERBOSE 0 #define TEST_SERVER_DUMP 1 @@ -26,6 +28,16 @@ #define PROXY_PORT 23456 +typedef struct serv_ctx_t serv_ctx_t; + +typedef apr_status_t (*send_func_t)(serv_ctx_t *serv_ctx, const char *data, + apr_size_t *len); +typedef apr_status_t (*receive_func_t)(serv_ctx_t *serv_ctx, char *data, + apr_size_t *len); + +typedef apr_status_t (*handshake_func_t)(serv_ctx_t *serv_ctx); +typedef apr_status_t (*reset_conn_func_t)(serv_ctx_t *serv_ctx); + typedef struct { enum { @@ -33,7 +45,8 @@ SERVER_SEND, SERVER_RESPOND, SERVER_IGNORE_AND_KILL_CONNECTION, - SERVER_KILL_CONNECTION + SERVER_KILL_CONNECTION, + PROXY_FORWARD, } kind; const char *text; @@ -44,20 +57,88 @@ const char *text; } test_server_message_t; -apr_status_t test_start_server(serv_ctx_t **servctx_p, - apr_sockaddr_t *address, - test_server_message_t *message_list, - apr_size_t message_count, - test_server_action_t *action_list, - apr_size_t action_count, - apr_int32_t options, - apr_pool_t *pool); +struct serv_ctx_t { + /* Pool for resource allocation. */ + apr_pool_t *pool; + serf_bucket_alloc_t *allocator; + + apr_int32_t options; + + /* Array of actions which server will replay when client connected. */ + test_server_action_t *action_list; + /* Size of action_list array. */ + apr_size_t action_count; + /* Index of current action. */ + apr_size_t cur_action; + + /* Array of messages the server will receive from the client. */ + test_server_message_t *message_list; + /* Size of message_list array. */ + apr_size_t message_count; + /* Index of current message. */ + apr_size_t cur_message; + + /* Number of messages received that the server didn't respond to yet. */ + apr_size_t outstanding_responses; + + /* Position in message buffer (incoming messages being read). */ + apr_size_t message_buf_pos; + + /* Position in action buffer. (outgoing messages being sent). */ + apr_size_t action_buf_pos; + + /* Address for server binding. */ + apr_sockaddr_t *serv_addr; + apr_socket_t *serv_sock; + + /* Accepted client socket. NULL if there is no client socket. */ + apr_socket_t *client_sock; + + /* Client socket to a server, in case this server acts as a proxy. */ + apr_socket_t *proxy_client_sock; + + serf_bucket_t *clientstream; + serf_bucket_t *servstream; + + send_func_t send; + receive_func_t read; + + /* SSL related variables */ + handshake_func_t handshake; + reset_conn_func_t reset; + + void *ssl_ctx; + const char *client_cn; + apr_status_t bio_read_status; +}; + +void setup_test_server(serv_ctx_t **servctx_p, + apr_sockaddr_t *address, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + apr_pool_t *pool); + +void setup_https_test_server(serv_ctx_t **servctx_p, + apr_sockaddr_t *address, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + const char *keyfile, + const char **certfiles, + const char *client_cn, + apr_pool_t *pool); + +apr_status_t start_test_server(serv_ctx_t *serv_ctx); -apr_status_t test_server_run(serv_ctx_t *servctx, +apr_status_t run_test_server(serv_ctx_t *servctx, apr_short_interval_time_t duration, apr_pool_t *pool); -apr_status_t test_server_destroy(serv_ctx_t *servctx, apr_pool_t *pool); #ifndef APR_VERSION_AT_LEAST /* Introduced in APR 1.3.0 */ #define APR_VERSION_AT_LEAST(major,minor,patch) \ @@ -67,4 +148,5 @@ (patch) <= APR_PATCH_VERSION)) #endif /* APR_VERSION_AT_LEAST */ + #endif /* TEST_SERVER_H */ diff -Nru serf-1.1.0/test/server/test_sslserver.c serf-1.3.3/test/server/test_sslserver.c --- serf-1.1.0/test/server/test_sslserver.c 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/server/test_sslserver.c 2013-07-21 14:21:27.000000000 +0000 @@ -0,0 +1,424 @@ +/* Copyright 2013 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "serf.h" +#include "test_server.h" + +#include "serf_private.h" + +#include +#include +#include + +static int init_done = 0; + +typedef struct ssl_context_t { + int handshake_done; + + SSL_CTX* ctx; + SSL* ssl; + BIO *bio; + +} ssl_context_t; + +static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) +{ + strncpy(buf, "serftest", size); + buf[size - 1] = '\0'; + return strlen(buf); +} + +static int bio_apr_socket_create(BIO *bio) +{ + bio->shutdown = 1; + bio->init = 1; + bio->num = -1; + bio->ptr = NULL; + + return 1; +} + +static int bio_apr_socket_destroy(BIO *bio) +{ + /* Did we already free this? */ + if (bio == NULL) { + return 0; + } + + return 1; +} + +static long bio_apr_socket_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + long ret = 1; + + switch (cmd) { + default: + /* abort(); */ + break; + case BIO_CTRL_FLUSH: + /* At this point we can't force a flush. */ + break; + case BIO_CTRL_PUSH: + case BIO_CTRL_POP: + ret = 0; + break; + } + return ret; +} + +/* Returns the amount read. */ +static int bio_apr_socket_read(BIO *bio, char *in, int inlen) +{ + apr_size_t len = inlen; + serv_ctx_t *serv_ctx = bio->ptr; + apr_status_t status; + + BIO_clear_retry_flags(bio); + + status = apr_socket_recv(serv_ctx->client_sock, in, &len); + serv_ctx->bio_read_status = status; + serf__log_skt(TEST_VERBOSE, __FILE__, serv_ctx->client_sock, + "Read %d bytes from socket with status %d.\n", len, status); + + if (status == APR_EAGAIN) { + BIO_set_retry_read(bio); + if (len == 0) + return -1; + } + + if (SERF_BUCKET_READ_ERROR(status)) + return -1; + + return len; +} + +/* Returns the amount written. */ +static int bio_apr_socket_write(BIO *bio, const char *in, int inlen) +{ + apr_size_t len = inlen; + serv_ctx_t *serv_ctx = bio->ptr; + + apr_status_t status = apr_socket_send(serv_ctx->client_sock, in, &len); + + serf__log_skt(TEST_VERBOSE, __FILE__, serv_ctx->client_sock, + "Wrote %d of %d bytes to socket with status %d.\n", + len, inlen, status); + + if (SERF_BUCKET_READ_ERROR(status)) + return -1; + + return len; +} + + +static BIO_METHOD bio_apr_socket_method = { + BIO_TYPE_SOCKET, + "APR sockets", + bio_apr_socket_write, + bio_apr_socket_read, + NULL, /* Is this called? */ + NULL, /* Is this called? */ + bio_apr_socket_ctrl, + bio_apr_socket_create, + bio_apr_socket_destroy, +#ifdef OPENSSL_VERSION_NUMBER + NULL /* sslc does not have the callback_ctrl field */ +#endif +}; + +static int validate_client_certificate(int preverify_ok, X509_STORE_CTX *ctx) +{ + serf__log(TEST_VERBOSE, __FILE__, "validate_client_certificate called, " + "preverify code: %d.\n", preverify_ok); + + return preverify_ok; +} + +static apr_status_t init_ssl(serv_ctx_t *serv_ctx) +{ + ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx; + + ssl_ctx->ssl = SSL_new(ssl_ctx->ctx); + SSL_set_cipher_list(ssl_ctx->ssl, "ALL"); + SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio); + + return APR_SUCCESS; +} + +static apr_status_t +init_ssl_context(serv_ctx_t *serv_ctx, + const char *keyfile, + const char **certfiles, + const char *client_cn) +{ + ssl_context_t *ssl_ctx = apr_pcalloc(serv_ctx->pool, sizeof(*ssl_ctx)); + serv_ctx->ssl_ctx = ssl_ctx; + serv_ctx->client_cn = client_cn; + serv_ctx->bio_read_status = APR_SUCCESS; + + /* Init OpenSSL globally */ + if (!init_done) + { + CRYPTO_malloc_init(); + ERR_load_crypto_strings(); + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + init_done = 1; + } + + /* Init this connection */ + if (!ssl_ctx->ctx) { + X509_STORE *store; + const char *certfile; + int i; + int rv; + + ssl_ctx->ctx = SSL_CTX_new(SSLv23_server_method()); + SSL_CTX_set_default_passwd_cb(ssl_ctx->ctx, pem_passwd_cb); + rv = SSL_CTX_use_PrivateKey_file(ssl_ctx->ctx, keyfile, + SSL_FILETYPE_PEM); + if (rv != 1) { + fprintf(stderr, "Cannot load private key from file '%s'\n", keyfile); + exit(1); + } + + /* Set server certificate, add ca certificates if provided. */ + certfile = certfiles[0]; + rv = SSL_CTX_use_certificate_file(ssl_ctx->ctx, certfile, SSL_FILETYPE_PEM); + if (rv != 1) { + fprintf(stderr, "Cannot load certficate from file '%s'\n", keyfile); + exit(1); + } + + i = 1; + certfile = certfiles[i++]; + store = SSL_CTX_get_cert_store(ssl_ctx->ctx); + + while(certfile) { + FILE *fp = fopen(certfile, "r"); + if (fp) { + X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL); + fclose(fp); + + SSL_CTX_add_extra_chain_cert(ssl_ctx->ctx, ssl_cert); + + X509_STORE_add_cert(store, ssl_cert); + } + certfile = certfiles[i++]; + } + + /* This makes the server send a client certificate request during + handshake. The client certificate is optional (most tests don't + send one) by default, but mandatory if client_cn was specified. */ + SSL_CTX_set_verify(ssl_ctx->ctx, SSL_VERIFY_PEER, + validate_client_certificate); + + SSL_CTX_set_mode(ssl_ctx->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); + + ssl_ctx->bio = BIO_new(&bio_apr_socket_method); + ssl_ctx->bio->ptr = serv_ctx; + init_ssl(serv_ctx); + } + + return APR_SUCCESS; +} + +static apr_status_t ssl_reset(serv_ctx_t *serv_ctx) +{ + ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx; + + serf__log(TEST_VERBOSE, __FILE__, "Reset ssl context.\n"); + + ssl_ctx->handshake_done = 0; + if (ssl_ctx) + SSL_clear(ssl_ctx->ssl); + init_ssl(serv_ctx); + + return APR_SUCCESS; +} + +static apr_status_t ssl_handshake(serv_ctx_t *serv_ctx) +{ + ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx; + int result; + + if (ssl_ctx->handshake_done) + return APR_SUCCESS; + + /* SSL handshake */ + result = SSL_accept(ssl_ctx->ssl); + if (result == 1) { + X509 *peer; + + serf__log(TEST_VERBOSE, __FILE__, "Handshake successful.\n"); + + /* Check client certificate */ + peer = SSL_get_peer_certificate(ssl_ctx->ssl); + if (peer) + { + serf__log(TEST_VERBOSE, __FILE__, "Peer cert received.\n"); + if (SSL_get_verify_result(ssl_ctx->ssl) == X509_V_OK) + { + /* The client sent a certificate which verified OK */ + char buf[1024]; + int ret; + X509_NAME *subject = X509_get_subject_name(peer); + + ret = X509_NAME_get_text_by_NID(subject, + NID_commonName, + buf, 1024); + if (ret != -1 && strcmp(serv_ctx->client_cn, buf) != 0) { + serf__log(TEST_VERBOSE, __FILE__, "Client cert common name " + "\"%s\" doesn't match expected \"%s\".\n", buf, + serv_ctx->client_cn); + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + } + } + } else { + if (serv_ctx->client_cn) { + serf__log(TEST_VERBOSE, __FILE__, "Client cert expected but not" + " received.\n"); + return SERF_ERROR_ISSUE_IN_TESTSUITE; + } + } + + ssl_ctx->handshake_done = 1; + } + else { + int ssl_err; + + ssl_err = SSL_get_error(ssl_ctx->ssl, result); + switch (ssl_err) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + return APR_EAGAIN; + case SSL_ERROR_SYSCALL: + return serv_ctx->bio_read_status; /* Usually APR_EAGAIN */ + default: + serf__log(TEST_VERBOSE, __FILE__, "SSL Error %d: ", ssl_err); + ERR_print_errors_fp(stderr); + serf__log_nopref(TEST_VERBOSE, "\n"); + return SERF_ERROR_ISSUE_IN_TESTSUITE; + } + } + + return APR_EAGAIN; +} + +static apr_status_t +ssl_socket_write(serv_ctx_t *serv_ctx, const char *data, + apr_size_t *len) +{ + ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx; + + int result = SSL_write(ssl_ctx->ssl, data, *len); + if (result > 0) { + *len = result; + return APR_SUCCESS; + } + + if (result == 0) + return APR_EAGAIN; + + serf__log(TEST_VERBOSE, __FILE__, "ssl_socket_write: ssl error?\n"); + + return SERF_ERROR_ISSUE_IN_TESTSUITE; +} + +static apr_status_t +ssl_socket_read(serv_ctx_t *serv_ctx, char *data, + apr_size_t *len) +{ + ssl_context_t *ssl_ctx = serv_ctx->ssl_ctx; + + int result = SSL_read(ssl_ctx->ssl, data, *len); + if (result > 0) { + *len = result; + return APR_SUCCESS; + } else { + int ssl_err; + + ssl_err = SSL_get_error(ssl_ctx->ssl, result); + switch (ssl_err) { + case SSL_ERROR_SYSCALL: + /* error in bio_bucket_read, probably APR_EAGAIN or APR_EOF */ + *len = 0; + return serv_ctx->bio_read_status; + case SSL_ERROR_WANT_READ: + *len = 0; + return APR_EAGAIN; + case SSL_ERROR_SSL: + default: + *len = 0; + serf__log(TEST_VERBOSE, __FILE__, + "ssl_socket_read SSL Error %d: ", ssl_err); + ERR_print_errors_fp(stderr); + serf__log_nopref(TEST_VERBOSE, "\n"); + return SERF_ERROR_ISSUE_IN_TESTSUITE; + } + } + + /* not reachable */ + return SERF_ERROR_ISSUE_IN_TESTSUITE; +} + +static apr_status_t cleanup_https_server(void *baton) +{ + serv_ctx_t *servctx = baton; + ssl_context_t *ssl_ctx = servctx->ssl_ctx; + + if (ssl_ctx) { + if (ssl_ctx->ssl) + SSL_clear(ssl_ctx->ssl); + SSL_CTX_free(ssl_ctx->ctx); + } + + return APR_SUCCESS; +} + +void setup_https_test_server(serv_ctx_t **servctx_p, + apr_sockaddr_t *address, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + const char *keyfile, + const char **certfiles, + const char *client_cn, + apr_pool_t *pool) +{ + serv_ctx_t *servctx; + + setup_test_server(servctx_p, address, message_list, + message_count, action_list, action_count, + options, pool); + servctx = *servctx_p; + apr_pool_cleanup_register(pool, servctx, + cleanup_https_server, + apr_pool_cleanup_null); + + servctx->handshake = ssl_handshake; + servctx->reset = ssl_reset; + + /* Override with SSL encrypt/decrypt functions */ + servctx->read = ssl_socket_read; + servctx->send = ssl_socket_write; + + init_ssl_context(servctx, keyfile, certfiles, client_cn); +} diff -Nru serf-1.1.0/test/test_all.c serf-1.3.3/test/test_all.c --- serf-1.1.0/test/test_all.c 2010-09-19 20:35:46.000000000 +0000 +++ serf-1.3.3/test/test_all.c 2013-06-13 07:41:45.000000000 +0000 @@ -25,6 +25,11 @@ {"context", test_context}, {"buckets", test_buckets}, {"ssl", test_ssl}, + {"auth", test_auth}, +#if 0 + /* internal test for the mock bucket. */ + {"mock", test_mock_bucket}, +#endif {"LastTest", NULL} }; diff -Nru serf-1.1.0/test/test_auth.c serf-1.3.3/test/test_auth.c --- serf-1.1.0/test/test_auth.c 1970-01-01 00:00:00.000000000 +0000 +++ serf-1.3.3/test/test_auth.c 2013-09-29 06:37:46.000000000 +0000 @@ -0,0 +1,629 @@ +/* Copyright 2013 Justin Erenkrantz and Greg Stein + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "serf.h" +#include "test_serf.h" + +static apr_status_t +authn_callback_expect_not_called(char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) +{ + handler_baton_t *handler_ctx = baton; + test_baton_t *tb = handler_ctx->tb; + + tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; + + /* Should not have been called. */ + return SERF_ERROR_ISSUE_IN_TESTSUITE; +} + +/* Tests that authn fails if all authn schemes are disabled. */ +static void test_authentication_disabled(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[2]; + + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")} }; + test_server_action_t action_list[] = { + {SERVER_RESPOND, "HTTP/1.1 401 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "WWW-Authenticate: Basic realm=""Test Suite""" CRLF + CRLF + "1" CRLF CRLF + "0" CRLF CRLF}, + }; + apr_status_t status; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, 1, + action_list, 1, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + serf_config_authn_types(tb->context, SERF_AUTHN_NONE); + serf_config_credentials_callback(tb->context, + authn_callback_expect_not_called); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + status = test_helper_run_requests_no_check(tc, tb, 1, + handler_ctx, test_pool); + CuAssertIntEquals(tc, SERF_ERROR_AUTHN_NOT_SUPPORTED, status); + CuAssertIntEquals(tc, 1, tb->sent_requests->nelts); + CuAssertIntEquals(tc, 1, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, 0, tb->handled_requests->nelts); + + CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); +} + +/* Tests that authn fails if encountered an unsupported scheme. */ +static void test_unsupported_authentication(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[2]; + + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")} }; + test_server_action_t action_list[] = { + {SERVER_RESPOND, "HTTP/1.1 401 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "WWW-Authenticate: NotExistent realm=""Test Suite""" CRLF + CRLF + "1" CRLF CRLF + "0" CRLF CRLF}, + }; + apr_status_t status; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, 1, + action_list, 1, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + serf_config_authn_types(tb->context, SERF_AUTHN_ALL); + serf_config_credentials_callback(tb->context, + authn_callback_expect_not_called); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + status = test_helper_run_requests_no_check(tc, tb, 1, + handler_ctx, test_pool); + CuAssertIntEquals(tc, SERF_ERROR_AUTHN_NOT_SUPPORTED, status); + CuAssertIntEquals(tc, 1, tb->sent_requests->nelts); + CuAssertIntEquals(tc, 1, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, 0, tb->handled_requests->nelts); + + CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); +} + +static apr_status_t +basic_authn_callback(char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) +{ + handler_baton_t *handler_ctx = baton; + test_baton_t *tb = handler_ctx->tb; + + tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; + + if (code != 401) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Basic", authn_type) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp(" Test Suite", realm) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + *username = "serf"; + *password = "serftest"; + + return APR_SUCCESS; +} + +/* Test template, used for KeepAlive Off and KeepAlive On test */ +static void basic_authentication(CuTest *tc, const char *resp_hdrs) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[2]; + int num_requests_sent, num_requests_recvd; + test_server_message_t message_list[3]; + test_server_action_t action_list[3]; + apr_status_t status; + + apr_pool_t *test_pool = tc->testBaton; + + /* Expected string relies on strict order of headers, which is not + guaranteed. c2VyZjpzZXJmdGVzdA== is base64 encoded serf:serftest . */ + message_list[0].text = CHUNKED_REQUEST(1, "1"); + message_list[1].text = apr_psprintf(test_pool, + "GET / HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "1" CRLF + "0" CRLF CRLF); + message_list[2].text = apr_psprintf(test_pool, + "GET / HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "2" CRLF + "0" CRLF CRLF); + + action_list[0].kind = SERVER_RESPOND; + /* Use non-standard case WWW-Authenticate header and scheme name to test + for case insensitive comparisons. */ + action_list[0].text = apr_psprintf(test_pool, + "HTTP/1.1 401 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "www-Authenticate: bAsIc realm=""Test Suite""" CRLF + "%s" + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, resp_hdrs); + action_list[1].kind = SERVER_RESPOND; + action_list[1].text = CHUNKED_EMPTY_RESPONSE; + action_list[2].kind = SERVER_RESPOND; + action_list[2].text = CHUNKED_EMPTY_RESPONSE; + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, 3, + action_list, 3, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + serf_config_authn_types(tb->context, SERF_AUTHN_BASIC); + serf_config_credentials_callback(tb->context, basic_authn_callback); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + /* Test that a request is retried and authentication headers are set + correctly. */ + num_requests_sent = 1; + num_requests_recvd = 2; + + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); + CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); + + /* Test that credentials were cached by asserting that the authn callback + wasn't called again. */ + tb->result_flags = 0; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 2); + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); +} + +static void test_basic_authentication(CuTest *tc) +{ + basic_authentication(tc, ""); +} + +static void test_basic_authentication_keepalive_off(CuTest *tc) +{ + basic_authentication(tc, "Connection: close" CRLF); +} + +static apr_status_t +digest_authn_callback(char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) +{ + handler_baton_t *handler_ctx = baton; + test_baton_t *tb = handler_ctx->tb; + + tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; + + if (code != 401) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Digest", authn_type) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp(" Test Suite", realm) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + *username = "serf"; + *password = "serftest"; + + return APR_SUCCESS; +} + +/* Test template, used for KeepAlive Off and KeepAlive On test */ +static void digest_authentication(CuTest *tc, const char *resp_hdrs) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[2]; + int num_requests_sent, num_requests_recvd; + test_server_message_t message_list[2]; + test_server_action_t action_list[2]; + apr_pool_t *test_pool = tc->testBaton; + apr_status_t status; + + /* Expected string relies on strict order of headers and attributes of + Digest, both are not guaranteed. + 6ff0d4cc201513ce970d5c6b25e1043b is encoded as: + md5hex(md5hex("serf:Test Suite:serftest") & ":" & + md5hex("ABCDEF1234567890") & ":" & + md5hex("GET:/test/index.html")) + */ + message_list[0].text = CHUNKED_REQUEST_URI("/test/index.html", 1, "1"); + message_list[1].text = apr_psprintf(test_pool, + "GET /test/index.html HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: Digest realm=\"Test Suite\", username=\"serf\", " + "nonce=\"ABCDEF1234567890\", uri=\"/test/index.html\", " + "response=\"6ff0d4cc201513ce970d5c6b25e1043b\", opaque=\"myopaque\", " + "algorithm=\"MD5\"" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "1" CRLF + "0" CRLF CRLF); + action_list[0].kind = SERVER_RESPOND; + action_list[0].text = apr_psprintf(test_pool, + "HTTP/1.1 401 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "WWW-Authenticate: Digest realm=\"Test Suite\"," + "nonce=\"ABCDEF1234567890\",opaque=\"myopaque\"," + "algorithm=\"MD5\",qop-options=\"auth\"" CRLF + "%s" + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, resp_hdrs); + /* If the resp_hdrs includes "Connection: close", serf will automatically + reset the connection from the client side, no need to use + SERVER_KILL_CONNECTION. */ + action_list[1].kind = SERVER_RESPOND; + action_list[1].text = CHUNKED_EMPTY_RESPONSE; + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, 2, + action_list, 2, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* Add both Basic and Digest here, should use Digest only. */ + serf_config_authn_types(tb->context, SERF_AUTHN_BASIC | SERF_AUTHN_DIGEST); + serf_config_credentials_callback(tb->context, digest_authn_callback); + + create_new_request(tb, &handler_ctx[0], "GET", "/test/index.html", 1); + + /* Test that a request is retried and authentication headers are set + correctly. */ + num_requests_sent = 1; + num_requests_recvd = 2; + + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); + CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); +} + +static void test_digest_authentication(CuTest *tc) +{ + digest_authentication(tc, ""); +} + +static void test_digest_authentication_keepalive_off(CuTest *tc) +{ + /* Add the Connection: close header to the response with the Digest headers. + This to test that the Digest headers will be added to the retry of the + request on the new connection. */ + digest_authentication(tc, "Connection: close" CRLF); +} + +static apr_status_t +switched_realm_authn_callback(char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) +{ + handler_baton_t *handler_ctx = baton; + test_baton_t *tb = handler_ctx->tb; + const char *exp_realm = tb->user_baton; + + tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; + + if (code != 401) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp(exp_realm, realm) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + if (strcmp(realm, " Test Suite") == 0) { + *username = "serf"; + *password = "serftest"; + } else { + *username = "serf_newrealm"; + *password = "serftest"; + } + + return APR_SUCCESS; +} + +/* Test template, used for both Basic and Digest switch realms test */ +static void authentication_switch_realms(CuTest *tc, + const char *scheme, + const char *authn_attr, + const char *authz_attr_test_suite, + const char *authz_attr_wrong_realm, + const char *authz_attr_new_realm) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[2]; + int num_requests_sent, num_requests_recvd; + test_server_message_t message_list[5]; + test_server_action_t action_list[5]; + apr_pool_t *test_pool = tc->testBaton; + apr_status_t status; + + + message_list[0].text = CHUNKED_REQUEST(1, "1"); + message_list[1].text = apr_psprintf(test_pool, + "GET / HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: %s %s" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "1" CRLF + "0" CRLF CRLF, scheme, authz_attr_test_suite); + message_list[2].text = apr_psprintf(test_pool, + "GET / HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: %s %s" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "2" CRLF + "0" CRLF CRLF, scheme, authz_attr_test_suite); + /* The client doesn't know that /newrealm/ is in another realm, so it + reuses the credentials cached on the connection. */ + message_list[3].text = apr_psprintf(test_pool, + "GET /newrealm/index.html HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: %s %s" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "3" CRLF + "0" CRLF CRLF, scheme, authz_attr_wrong_realm); + message_list[4].text = apr_psprintf(test_pool, + "GET /newrealm/index.html HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: %s %s" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "3" CRLF + "0" CRLF CRLF, scheme, authz_attr_new_realm); + + action_list[0].kind = SERVER_RESPOND; + action_list[0].text = apr_psprintf(test_pool, + "HTTP/1.1 401 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "WWW-Authenticate: %s realm=""Test Suite""%s" CRLF + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, scheme, authn_attr); + action_list[1].kind = SERVER_RESPOND; + action_list[1].text = CHUNKED_EMPTY_RESPONSE; + action_list[2].kind = SERVER_RESPOND; + action_list[2].text = CHUNKED_EMPTY_RESPONSE; + action_list[3].kind = SERVER_RESPOND; + action_list[3].text = apr_psprintf(test_pool, + "HTTP/1.1 401 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "WWW-Authenticate: %s realm=""New Realm""%s" CRLF + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, scheme, authn_attr); + action_list[4].kind = SERVER_RESPOND; + action_list[4].text = CHUNKED_EMPTY_RESPONSE; + + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, 5, + action_list, 5, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + serf_config_authn_types(tb->context, SERF_AUTHN_BASIC | SERF_AUTHN_DIGEST); + serf_config_credentials_callback(tb->context, + switched_realm_authn_callback); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + /* Test that a request is retried and authentication headers are set + correctly. */ + num_requests_sent = 1; + num_requests_recvd = 2; + + tb->user_baton = " Test Suite"; + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); + CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); + + /* Test that credentials were cached by asserting that the authn callback + wasn't called again. */ + tb->result_flags = 0; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 2); + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); + + /* Switch realms. Test that serf asks the application for new + credentials. */ + tb->result_flags = 0; + tb->user_baton = " New Realm"; + + create_new_request(tb, &handler_ctx[0], "GET", "/newrealm/index.html", 3); + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); +} + +static void test_basic_switch_realms(CuTest *tc) +{ + authentication_switch_realms(tc, "Basic", "", "c2VyZjpzZXJmdGVzdA==", + "c2VyZjpzZXJmdGVzdA==", + "c2VyZl9uZXdyZWFsbTpzZXJmdGVzdA=="); +} + +static void test_digest_switch_realms(CuTest *tc) +{ + authentication_switch_realms(tc, "Digest", ",nonce=\"ABCDEF1234567890\"," + "opaque=\"myopaque\", algorithm=\"MD5\",qop-options=\"auth\"", + /* response hdr attribute for Test Suite realm, uri / */ + "realm=\"Test Suite\", username=\"serf\", nonce=\"ABCDEF1234567890\", " + "uri=\"/\", response=\"3511a71fec5c02ab1c9212711a8baa58\", " + "opaque=\"myopaque\", algorithm=\"MD5\"", + /* response hdr attribute for Test Suite realm, uri /newrealm/index.html */ + "realm=\"Test Suite\", username=\"serf\", nonce=\"ABCDEF1234567890\", " + "uri=\"/newrealm/index.html\", response=\"c6b673cf44ad16ef379930856b607344\", " + "opaque=\"myopaque\", algorithm=\"MD5\"", + /* response hdr attribute for New Realm realm, uri /newrealm/index.html */ + "realm=\"New Realm\", username=\"serf_newrealm\", nonce=\"ABCDEF1234567890\", " + "uri=\"/newrealm/index.html\", response=\"f93f07d1412e53c421f66741a89198cb\", " + "opaque=\"myopaque\", algorithm=\"MD5\""); +} + +static void test_auth_on_HEAD(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[2]; + int num_requests_sent, num_requests_recvd; + apr_status_t status; + apr_pool_t *test_pool = tc->testBaton; + + test_server_message_t message_list[] = { + { + "HEAD / HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + CRLF + }, + { + "HEAD / HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF + CRLF + }, + }; + test_server_action_t action_list[] = { + { + SERVER_RESPOND, + "HTTP/1.1 401 Unauthorized" CRLF + "WWW-Authenticate: Basic Realm=""Test Suite""" CRLF + CRLF + }, + { + SERVER_RESPOND, + "HTTP/1.1 200 Ok" CRLF + "Content-Type: text/html" CRLF + CRLF + }, + }; + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, 2, + action_list, 2, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + serf_config_authn_types(tb->context, SERF_AUTHN_BASIC); + serf_config_credentials_callback(tb->context, basic_authn_callback); + + create_new_request(tb, &handler_ctx[0], "HEAD", "/", -1); + + /* Test that a request is retried and authentication headers are set + correctly. */ + num_requests_sent = 1; + num_requests_recvd = 2; + + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); + CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); +} + +/*****************************************************************************/ +CuSuite *test_auth(void) +{ + CuSuite *suite = CuSuiteNew(); + + CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown); + + SUITE_ADD_TEST(suite, test_authentication_disabled); + SUITE_ADD_TEST(suite, test_unsupported_authentication); + SUITE_ADD_TEST(suite, test_basic_authentication); + SUITE_ADD_TEST(suite, test_basic_authentication_keepalive_off); + SUITE_ADD_TEST(suite, test_digest_authentication); + SUITE_ADD_TEST(suite, test_digest_authentication_keepalive_off); + SUITE_ADD_TEST(suite, test_basic_switch_realms); + SUITE_ADD_TEST(suite, test_digest_switch_realms); + SUITE_ADD_TEST(suite, test_auth_on_HEAD); + + return suite; +} diff -Nru serf-1.1.0/test/test_buckets.c serf-1.3.3/test/test_buckets.c --- serf-1.1.0/test/test_buckets.c 2011-06-24 02:03:57.000000000 +0000 +++ serf-1.3.3/test/test_buckets.c 2013-09-29 06:37:46.000000000 +0000 @@ -20,7 +20,138 @@ #include "serf.h" #include "test_serf.h" -#define CRLF "\r\n" +/* test case has access to internal functions. */ +#include "serf_private.h" +#include "serf_bucket_util.h" + +static apr_status_t read_all(serf_bucket_t *bkt, + char *buf, + apr_size_t buf_len, + apr_size_t *read_len) +{ + const char *data; + apr_size_t data_len; + apr_status_t status; + apr_size_t read; + + read = 0; + + do + { + status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &data_len); + + if (!SERF_BUCKET_READ_ERROR(status)) + { + if (data_len > buf_len - read) + { + /* Buffer is not large enough to read all data */ + data_len = buf_len - read; + status = SERF_ERROR_ISSUE_IN_TESTSUITE; + } + memcpy(buf + read, data, data_len); + read += data_len; + } + } while(status == APR_SUCCESS); + + *read_len = read; + return status; +} + +/* Reads bucket until EOF found and compares read data with zero terminated + string expected. Report all failures using CuTest. */ +void read_and_check_bucket(CuTest *tc, serf_bucket_t *bkt, + const char *expected) +{ + apr_status_t status; + do + { + const char *data; + apr_size_t len; + + status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); + CuAssert(tc, "Got error during bucket reading.", + !SERF_BUCKET_READ_ERROR(status)); + CuAssert(tc, "Read more data than expected.", + strlen(expected) >= len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp(expected, data, len) == 0); + + expected += len; + } while(!APR_STATUS_IS_EOF(status)); + + CuAssert(tc, "Read less data than expected.", strlen(expected) == 0); +} + +/* Reads bucket with serf_bucket_readline until EOF found and compares: + - actual line endings with expected line endings + - actual data with zero terminated string expected. + Reports all failures using CuTest. */ +void readlines_and_check_bucket(CuTest *tc, serf_bucket_t *bkt, + int acceptable, + const char *expected, + int expected_nr_of_lines) +{ + apr_status_t status; + int actual_nr_of_lines = 0; + + do + { + const char *data; + apr_size_t len; + int found; + + status = serf_bucket_readline(bkt, acceptable, &found, + &data, &len); + CuAssert(tc, "Got error during bucket reading.", + !SERF_BUCKET_READ_ERROR(status)); + CuAssert(tc, "Read more data than expected.", + strlen(expected) >= len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp(expected, data, len) == 0); + + expected += len; + + if (found == SERF_NEWLINE_CRLF_SPLIT) + continue; + + if (found != SERF_NEWLINE_NONE) + { + actual_nr_of_lines++; + + CuAssert(tc, "Unexpected line ending type!", + found & acceptable); + if (found & SERF_NEWLINE_CR) + CuAssert(tc, "CR Line ending was reported but not in data!", + strncmp(data + len - 1, "\r", 1) == 0); + if (found & SERF_NEWLINE_LF) + CuAssert(tc, "LF Line ending was reported but not in data!", + strncmp(data + len - 1, "\n", 1) == 0); + if (found & SERF_NEWLINE_CRLF) + CuAssert(tc, "CRLF Line ending was reported but not in data!", + strncmp(data + len - 2, "\r\n", 2) == 0); + } else + { + if (status == APR_EOF && len) + actual_nr_of_lines++; + + if (acceptable & SERF_NEWLINE_CR) + CuAssert(tc, "CR Line ending was not reported but in data!", + strncmp(data + len - 1, "\r", 1) != 0); + if (acceptable & SERF_NEWLINE_LF) + CuAssert(tc, "LF Line ending was not reported but in data!", + strncmp(data + len - 1, "\n", 1) != 0); + if (acceptable & SERF_NEWLINE_CRLF) + CuAssert(tc, "CRLF Line ending was not reported but in data!", + strncmp(data + len - 2, "\r\n", 2) != 0); + } + } while(!APR_STATUS_IS_EOF(status)); + + CuAssertIntEquals(tc, expected_nr_of_lines, actual_nr_of_lines); + CuAssert(tc, "Read less data than expected.", strlen(expected) == 0); +} + + +/******************************** TEST CASES **********************************/ static void test_simple_bucket_readline(CuTest *tc) { @@ -29,15 +160,16 @@ const char *data; int found; apr_size_t len; - - apr_pool_t *test_pool = test_setup(); + const char *body; + + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); bkt = SERF_BUCKET_SIMPLE_STRING( - "line1" CRLF - "line2", - alloc); + "line1" CRLF + "line2", + alloc); /* Initialize parameters to check that they will be initialized. */ len = 0x112233; @@ -58,39 +190,47 @@ CuAssertIntEquals(tc, SERF_NEWLINE_NONE, found); CuAssertIntEquals(tc, 5, len); CuAssert(tc, data, strncmp("line2", data, len) == 0); - test_teardown(test_pool); -} - -/* Reads bucket until EOF found and compares read data with zero terminated - string expected. Report all failures using CuTest. */ -static void read_and_check_bucket(CuTest *tc, serf_bucket_t *bkt, - const char *expected) -{ - apr_status_t status; - do - { - const char *data; - apr_size_t len; - - status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); - CuAssert(tc, "Got error during bucket reading.", - !SERF_BUCKET_READ_ERROR(status)); - CuAssert(tc, "Read more data than expected.", - strlen(expected) >= len); - CuAssert(tc, "Read data is not equal to expected.", - strncmp(expected, data, len) == 0); - expected += len; - } while(!APR_STATUS_IS_EOF(status)); + /* acceptable line types should be reported */ + bkt = SERF_BUCKET_SIMPLE_STRING("line1" CRLF, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_CRLF, "line1" CRLF, 1); + bkt = SERF_BUCKET_SIMPLE_STRING("line1" LF, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_LF, "line1" LF, 1); + bkt = SERF_BUCKET_SIMPLE_STRING("line1" LF, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_LF, "line1" LF, 1); + /* special cases, but acceptable */ + bkt = SERF_BUCKET_SIMPLE_STRING("line1" CRLF, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_CR, "line1" CRLF, 2); + bkt = SERF_BUCKET_SIMPLE_STRING("line1" CRLF, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_LF, "line1" CRLF, 1); - CuAssert(tc, "Read less data than expected.", strlen(expected) == 0); + /* Unacceptable line types should not be reported */ + bkt = SERF_BUCKET_SIMPLE_STRING("line1" LF, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_CR, "line1" LF, 1); + bkt = SERF_BUCKET_SIMPLE_STRING("line1" LF, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_CRLF, "line1" LF, 1); + bkt = SERF_BUCKET_SIMPLE_STRING("line1" CR, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_LF, "line1" CR, 1); +#if 0 + /* TODO: looks like a bug, CRLF acceptable on buffer with CR returns + SERF_NEWLINE_CRLF_SPLIT, but here that CR comes at the end of the + buffer (APR_EOF), so should have been SERF_NEWLINE_NONE! */ + bkt = SERF_BUCKET_SIMPLE_STRING("line1" CR, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_CRLF, "line1" CR, 1); +#endif + + body = "12345678901234567890" CRLF + "12345678901234567890" CRLF + "12345678901234567890" CRLF; + bkt = SERF_BUCKET_SIMPLE_STRING(body, alloc); + readlines_and_check_bucket(tc, bkt, SERF_NEWLINE_LF, body, 3); } static void test_response_bucket_read(CuTest *tc) { serf_bucket_t *bkt, *tmp; - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); @@ -105,14 +245,13 @@ /* Read all bucket and check it content. */ read_and_check_bucket(tc, bkt, "abc1234"); - test_teardown(test_pool); } static void test_response_bucket_headers(CuTest *tc) { serf_bucket_t *bkt, *tmp, *hdr; - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); @@ -143,14 +282,13 @@ CuAssertStrEquals(tc, "", serf_bucket_headers_get(hdr, "NoSpace")); - test_teardown(test_pool); } static void test_response_bucket_chunked_read(CuTest *tc) { serf_bucket_t *bkt, *tmp, *hdrs; - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); @@ -177,12 +315,11 @@ /* Check that trailing headers parsed correctly. */ CuAssertStrEquals(tc, "value", serf_bucket_headers_get(hdrs, "Footer")); - test_teardown(test_pool); } static void test_bucket_header_set(CuTest *tc) { - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); serf_bucket_t *hdrs = serf_bucket_headers_create(alloc); @@ -201,34 +338,8 @@ CuAssertStrEquals(tc, "bar,baz,test", serf_bucket_headers_get(hdrs, "Foo")); - // headers are case insensitive. + /* headers are case insensitive. */ CuAssertStrEquals(tc, "bar,baz,test", serf_bucket_headers_get(hdrs, "fOo")); - test_teardown(test_pool); -} - -static apr_status_t read_requested_bytes(serf_bucket_t *bkt, - apr_size_t requested, - const char **buf, - apr_size_t *len, - apr_pool_t *pool) -{ - apr_size_t current = 0; - const char *tmp; - const char *data; - apr_status_t status = APR_SUCCESS; - - tmp = apr_pcalloc(pool, requested); - while (current < requested) { - status = serf_bucket_read(bkt, requested, &data, len); - memcpy((void*)(tmp + current), (void*)data, *len); - current += *len; - if (APR_STATUS_IS_EOF(status)) - break; - } - - *buf = tmp; - *len = current; - return status; } @@ -243,7 +354,7 @@ int i; int vecs_used; - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); @@ -380,8 +491,44 @@ tgt_vecs, &vecs_used); CuAssertIntEquals(tc, APR_SUCCESS, status); CuAssertIntEquals(tc, 0, vecs_used); +} + +/* Construct a header bucket with some headers, and then read from it. */ +static void test_header_buckets(CuTest *tc) +{ + apr_status_t status; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + const char *cur; + + serf_bucket_t *hdrs = serf_bucket_headers_create(alloc); + CuAssertTrue(tc, hdrs != NULL); + + serf_bucket_headers_set(hdrs, "Content-Type", "text/plain"); + serf_bucket_headers_set(hdrs, "Content-Length", "100"); + + /* Note: order not guaranteed, assume here that it's fifo. */ + cur = "Content-Type: text/plain" CRLF + "Content-Length: 100" CRLF + CRLF + CRLF; + while (1) { + const char *data; + apr_size_t len; + + status = serf_bucket_read(hdrs, SERF_READ_ALL_AVAIL, &data, &len); + CuAssert(tc, "Unexpected error when waiting for response headers", + !SERF_BUCKET_READ_ERROR(status)); + if (SERF_BUCKET_READ_ERROR(status) || + APR_STATUS_IS_EOF(status)) + break; - test_teardown(test_pool); + /* Check that the bytes read match with expected at current position. */ + CuAssertStrnEquals(tc, cur, len, data); + cur += len; + } + CuAssertIntEquals(tc, APR_EOF, status); } static void test_aggregate_buckets(CuTest *tc) @@ -390,15 +537,21 @@ serf_bucket_t *bkt, *aggbkt; struct iovec tgt_vecs[32]; int vecs_used; + apr_size_t len; + const char *data; - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); + const char *BODY = "12345678901234567890"\ + "12345678901234567890"\ + "12345678901234567890"\ + CRLF; /* Test 1: read 0 bytes from an aggregate */ aggbkt = serf_bucket_aggregate_create(alloc); - bkt = SERF_BUCKET_SIMPLE_STRING("line1" CRLF, alloc); + bkt = SERF_BUCKET_SIMPLE_STRING(BODY, alloc); serf_bucket_aggregate_append(aggbkt, bkt); status = serf_bucket_read_iovec(aggbkt, 0, 32, @@ -406,20 +559,693 @@ CuAssertIntEquals(tc, APR_SUCCESS, status); CuAssertIntEquals(tc, 0, vecs_used); - test_teardown(test_pool); + + /* Test 2: peek the available bytes, should be non-0 */ + len = SERF_READ_ALL_AVAIL; + status = serf_bucket_peek(aggbkt, &data, &len); + + /* status should be either APR_SUCCESS or APR_EOF */ + if (status == APR_SUCCESS) + CuAssertTrue(tc, len > 0 && len < strlen(BODY)); + else if (status == APR_EOF) + CuAssertIntEquals(tc, strlen(BODY), len); + else + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* Test 3: read the data from the bucket. */ + read_and_check_bucket(tc, aggbkt, BODY); + + /* Test 4: multiple child buckets appended. */ + aggbkt = serf_bucket_aggregate_create(alloc); + + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY, 15, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY+15, strlen(BODY)-15, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); + + read_and_check_bucket(tc, aggbkt, BODY); + + /* Test 5: multiple child buckets prepended. */ + aggbkt = serf_bucket_aggregate_create(alloc); + + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY+15, strlen(BODY)-15, alloc); + serf_bucket_aggregate_prepend(aggbkt, bkt); + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY, 15, alloc); + serf_bucket_aggregate_prepend(aggbkt, bkt); + + read_and_check_bucket(tc, aggbkt, BODY); + + /* Test 6: ensure peek doesn't return APR_EAGAIN, or APR_EOF incorrectly. */ + aggbkt = serf_bucket_aggregate_create(alloc); + + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY, 15, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY+15, strlen(BODY)-15, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); + + len = 1234; + status = serf_bucket_peek(aggbkt, &data, &len); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssert(tc, "Length should be positive.", + len > 0 && len <= strlen(BODY) ); + CuAssert(tc, "Data should match first part of body.", + strncmp(BODY, data, len) == 0); +} + +static void test_aggregate_bucket_readline(CuTest *tc) +{ + serf_bucket_t *bkt, *aggbkt; + apr_pool_t *test_pool = tc->testBaton; + + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + const char *BODY = "12345678901234567890" CRLF + "12345678901234567890" CRLF + "12345678901234567890" CRLF; + + /* Test 1: read lines from an aggregate bucket */ + aggbkt = serf_bucket_aggregate_create(alloc); + + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY, 22, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); /* 1st line */ + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY+22, strlen(BODY)-22, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); /* 2nd and 3rd line */ + + bkt = SERF_BUCKET_SIMPLE_STRING(BODY, alloc); + readlines_and_check_bucket(tc, aggbkt, SERF_NEWLINE_CRLF, BODY, 3); + + /* Test 2: start with empty bucket */ + aggbkt = serf_bucket_aggregate_create(alloc); + + bkt = SERF_BUCKET_SIMPLE_STRING_LEN("", 0, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); /* empty bucket */ + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY, 22, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); /* 1st line */ + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY+22, strlen(BODY)-22, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); /* 2nd and 3rd line */ + + bkt = SERF_BUCKET_SIMPLE_STRING(BODY, alloc); + readlines_and_check_bucket(tc, aggbkt, SERF_NEWLINE_CRLF, BODY, 3); +} + +/* Test for issue: the server aborts the connection in the middle of + streaming the body of the response, where the length was set with the + Content-Length header. Test that we get a decent error code from the + response bucket instead of APR_EOF. */ +static void test_response_body_too_small_cl(CuTest *tc) +{ + serf_bucket_t *bkt, *tmp; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + + /* Make a response of 60 bytes, but set the Content-Length to 100. */ +#define BODY "12345678901234567890"\ + "12345678901234567890"\ + "12345678901234567890" + + tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF + "Content-Length: 100" CRLF + CRLF + BODY, + alloc); + + bkt = serf_bucket_response_create(tmp, alloc); + + { + const char *data; + apr_size_t len; + apr_status_t status; + + status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); + + CuAssert(tc, "Read more data than expected.", + strlen(BODY) >= len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp(BODY, data, len) == 0); + CuAssert(tc, "Error expected due to response body too short!", + SERF_BUCKET_READ_ERROR(status)); + CuAssertIntEquals(tc, SERF_ERROR_TRUNCATED_HTTP_RESPONSE, status); + } +} +#undef BODY + +/* Test for issue: the server aborts the connection in the middle of + streaming the body of the response, using chunked encoding. Test that we get + a decent error code from the response bucket instead of APR_EOF. */ +static void test_response_body_too_small_chunked(CuTest *tc) +{ + serf_bucket_t *bkt, *tmp; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + + /* Make a response of 60 bytes, but set the chunk size to 60 and don't end + with chunk of length 0. */ +#define BODY "12345678901234567890"\ +"12345678901234567890"\ +"12345678901234567890" + + tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "64" CRLF BODY, + alloc); + + bkt = serf_bucket_response_create(tmp, alloc); + + { + const char *data; + apr_size_t len; + apr_status_t status; + + status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); + + CuAssert(tc, "Read more data than expected.", + strlen(BODY) >= len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp(BODY, data, len) == 0); + CuAssert(tc, "Error expected due to response body too short!", + SERF_BUCKET_READ_ERROR(status)); + CuAssertIntEquals(tc, SERF_ERROR_TRUNCATED_HTTP_RESPONSE, status); + } +} +#undef BODY + +/* Test for issue: the server aborts the connection in the middle of + streaming trailing CRLF after body chunk. Test that we get + a decent error code from the response bucket instead of APR_EOF. */ +static void test_response_body_chunked_no_crlf(CuTest *tc) +{ + serf_bucket_t *bkt, *tmp; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + + tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "2" CRLF + "AB", + alloc); + + bkt = serf_bucket_response_create(tmp, alloc); + + { + char buf[1024]; + apr_size_t len; + apr_status_t status; + + status = read_all(bkt, buf, sizeof(buf), &len); + + CuAssertIntEquals(tc, SERF_ERROR_TRUNCATED_HTTP_RESPONSE, status); + } +} + +/* Test for issue: the server aborts the connection in the middle of + streaming trailing CRLF after body chunk. Test that we get + a decent error code from the response bucket instead of APR_EOF. */ +static void test_response_body_chunked_incomplete_crlf(CuTest *tc) +{ + serf_bucket_t *bkt, *tmp; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + + tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "2" CRLF + "AB" + "\r", + alloc); + + bkt = serf_bucket_response_create(tmp, alloc); + + { + char buf[1024]; + apr_size_t len; + apr_status_t status; + + status = read_all(bkt, buf, sizeof(buf), &len); + + CuAssertIntEquals(tc, SERF_ERROR_TRUNCATED_HTTP_RESPONSE, status); + } +} + +static void test_response_body_chunked_gzip_small(CuTest *tc) +{ + serf_bucket_t *bkt, *tmp; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + + tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF + "Transfer-Encoding: chunked" CRLF + "Content-Encoding: gzip" CRLF + CRLF + "2" CRLF + "A", + alloc); + + bkt = serf_bucket_response_create(tmp, alloc); + + { + char buf[1024]; + apr_size_t len; + apr_status_t status; + + status = read_all(bkt, buf, sizeof(buf), &len); + + CuAssertIntEquals(tc, SERF_ERROR_TRUNCATED_HTTP_RESPONSE, status); + } +} + +static void test_response_bucket_peek_at_headers(CuTest *tc) +{ + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_t *resp_bkt1, *tmp, *hdrs; + serf_status_line sl; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + const char *hdr_val, *cur; + apr_status_t status; + +#define EXP_RESPONSE "HTTP/1.1 200 OK" CRLF\ + "Content-Type: text/plain" CRLF\ + "Content-Length: 100" CRLF\ + CRLF\ + "12345678901234567890"\ + "12345678901234567890"\ + "12345678901234567890" + + tmp = SERF_BUCKET_SIMPLE_STRING(EXP_RESPONSE, + alloc); + + resp_bkt1 = serf_bucket_response_create(tmp, alloc); + + status = serf_bucket_response_status(resp_bkt1, &sl); + CuAssertIntEquals(tc, 200, sl.code); + CuAssertStrEquals(tc, "OK", sl.reason); + CuAssertIntEquals(tc, SERF_HTTP_11, sl.version); + + /* Ensure that the status line & headers are read in the response_bucket. */ + status = serf_bucket_response_wait_for_headers(resp_bkt1); + CuAssert(tc, "Unexpected error when waiting for response headers", + !SERF_BUCKET_READ_ERROR(status)); + + hdrs = serf_bucket_response_get_headers(resp_bkt1); + CuAssertPtrNotNull(tc, hdrs); + + hdr_val = serf_bucket_headers_get(hdrs, "Content-Type"); + CuAssertStrEquals(tc, "text/plain", hdr_val); + hdr_val = serf_bucket_headers_get(hdrs, "Content-Length"); + CuAssertStrEquals(tc, "100", hdr_val); + + /* Create a new bucket for the response which still has the original + status line & headers. */ + + status = serf_response_full_become_aggregate(resp_bkt1); + CuAssertIntEquals(tc, APR_SUCCESS, status); + cur = EXP_RESPONSE; + + while (1) { + const char *data; + apr_size_t len; + apr_status_t status; + + status = serf_bucket_read(resp_bkt1, SERF_READ_ALL_AVAIL, &data, &len); + CuAssert(tc, "Unexpected error when waiting for response headers", + !SERF_BUCKET_READ_ERROR(status)); + if (SERF_BUCKET_READ_ERROR(status) || + APR_STATUS_IS_EOF(status)) + break; + + /* Check that the bytes read match with expected at current position. */ + CuAssertStrnEquals(tc, cur, len, data); + cur += len; + } + +} +#undef EXP_RESPONSE + +/* ### this test is useful, but needs to switch to the new COPY bucket + ### to test the behavior. */ +#if 0 + +/* Test that the internal function serf_default_read_iovec, used by many + bucket types, groups multiple buffers in one iovec. */ +static void test_serf_default_read_iovec(CuTest *tc) +{ + apr_status_t status; + serf_bucket_t *bkt, *aggbkt; + struct iovec tgt_vecs[32]; + int vecs_used, i; + apr_size_t actual_len = 0; + + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + const char *BODY = "12345678901234567890"\ + "12345678901234567890"\ + "12345678901234567890"\ + CRLF; + + /* Test 1: multiple children, should be read in one iovec. */ + aggbkt = serf_bucket_aggregate_create(alloc); + + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY, 20, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY+20, 20, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); + bkt = SERF_BUCKET_SIMPLE_STRING_LEN(BODY+40, strlen(BODY)-40, alloc); + serf_bucket_aggregate_append(aggbkt, bkt); + + status = serf_default_read_iovec(aggbkt, SERF_READ_ALL_AVAIL, 32, tgt_vecs, + &vecs_used); + CuAssertIntEquals(tc, APR_EOF, status); + for (i = 0; i < vecs_used; i++) + actual_len += tgt_vecs[i].iov_len; + CuAssertIntEquals(tc, strlen(BODY), actual_len); +} + +#endif + +/* Test that serf doesn't hang in an endless loop when a linebuf is in + split-CRLF state. */ +static void test_linebuf_crlf_split(CuTest *tc) +{ + serf_bucket_t *mock_bkt, *bkt; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + + mockbkt_action actions[]= { + { 1, "HTTP/1.1 200 OK" CRLF, APR_SUCCESS }, + { 1, "Content-Type: text/plain" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF, APR_SUCCESS }, + { 1, "6" CR, APR_SUCCESS }, + { 1, "", APR_EAGAIN }, + { 1, LF "blabla" CRLF CRLF, APR_SUCCESS }, }; + apr_status_t status; + + const char *expected = "blabla"; + + mock_bkt = serf_bucket_mock_create(actions, 5, alloc); + bkt = serf_bucket_response_create(mock_bkt, alloc); + + do + { + const char *data; + apr_size_t len; + + status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); + CuAssert(tc, "Got error during bucket reading.", + !SERF_BUCKET_READ_ERROR(status)); + CuAssert(tc, "Read more data than expected.", + strlen(expected) >= len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp(expected, data, len) == 0); + + expected += len; + + if (len == 0 && status == APR_EAGAIN) + serf_bucket_mock_more_data_arrived(mock_bkt); + } while(!APR_STATUS_IS_EOF(status)); + + CuAssert(tc, "Read less data than expected.", strlen(expected) == 0); +} + +/* Test that serf can handle lines that don't arrive completely in one go. + It doesn't really run random, it tries inserting APR_EAGAIN in all possible + places in the response message, only one currently. */ +static void test_random_eagain_in_response(CuTest *tc) +{ + apr_pool_t *test_pool = tc->testBaton; + apr_pool_t *iter_pool; + +#define BODY "12345678901234567890123456789012345678901234567890"\ + "12345678901234567890123456789012345678901234567890" + + const char *expected = apr_psprintf(test_pool, "%s%s", BODY, BODY); + const char *fullmsg = "HTTP/1.1 200 OK" CRLF + "Date: Fri, 12 Jul 2013 15:13:52 GMT" CRLF + "Server: Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/1.0.1e DAV/2 " + "mod_wsgi/3.4 Python/2.7.3 SVN/1.7.10" CRLF + "DAV: 1,2" CRLF + "DAV: version-control,checkout,working-resource" CRLF + "DAV: merge,baseline,activity,version-controlled-collection" CRLF + "DAV: http://subversion.tigris.org/xmlns/dav/svn/depth" CRLF + "DAV: http://subversion.tigris.org/xmlns/dav/svn/log-revprops" CRLF + "DAV: http://subversion.tigris.org/xmlns/dav/svn/atomic-revprops" CRLF + "DAV: http://subversion.tigris.org/xmlns/dav/svn/partial-replay" CRLF + "DAV: http://subversion.tigris.org/xmlns/dav/svn/mergeinfo" CRLF + "DAV: " CRLF + "MS-Author-Via: DAV" CRLF + "Allow: OPTIONS,GET,HEAD,POST,DELETE,TRACE,PROPFIND,PROPPATCH,COPY,MOVE," + "LOCK,UNLOCK,CHECKOUT" CRLF + "SVN-Youngest-Rev: 1502584" CRLF + "SVN-Repository-UUID: 13f79535-47bb-0310-9956-ffa450edef68" CRLF + "SVN-Repository-Root: /repos/asf" CRLF + "SVN-Me-Resource: /repos/asf/!svn/me" CRLF + "SVN-Rev-Root-Stub: /repos/asf/!svn/rvr" CRLF + "SVN-Rev-Stub: /repos/asf/!svn/rev" CRLF + "SVN-Txn-Root-Stub: /repos/asf/!svn/txr" CRLF + "SVN-Txn-Stub: /repos/asf/!svn/txn" CRLF + "SVN-VTxn-Root-Stub: /repos/asf/!svn/vtxr" CRLF + "SVN-VTxn-Stub: /repos/asf/!svn/vtxn" CRLF + "Vary: Accept-Encoding" CRLF + "Content-Type: text/plain" CRLF + "Content-Type: text/xml; charset=\"utf-8\"" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "64" CRLF + BODY CRLF + "64" CRLF + BODY CRLF + "0" CRLF + CRLF; + + const long nr_of_tests = strlen(fullmsg); + long i; + + mockbkt_action actions[]= { + { 1, NULL, APR_EAGAIN }, + { 1, NULL, APR_EAGAIN }, + }; + + apr_pool_create(&iter_pool, test_pool); + + for (i = 0; i < nr_of_tests; i++) { + serf_bucket_t *mock_bkt, *bkt; + serf_bucket_alloc_t *alloc; + const char *ptr = expected; + const char *part1, *part2; + apr_size_t cut; + apr_status_t status; + + apr_pool_clear(iter_pool); + + alloc = serf_bucket_allocator_create(iter_pool, NULL, NULL); + + cut = i % strlen(fullmsg); + part1 = apr_pstrndup(iter_pool, fullmsg, cut); + part2 = apr_pstrdup(iter_pool, fullmsg + cut); + + actions[0].data = part1; + actions[1].data = part2; + + mock_bkt = serf_bucket_mock_create(actions, 2, alloc); + bkt = serf_bucket_response_create(mock_bkt, alloc); + + do + { + const char *data, *errmsg; + apr_size_t len; + + status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); + CuAssert(tc, "Got error during bucket reading.", + !SERF_BUCKET_READ_ERROR(status)); + errmsg = apr_psprintf(iter_pool, + "Read more data than expected, EAGAIN" + " inserted at pos: %d, remainder: \"%s\"", + cut, fullmsg + cut); + CuAssert(tc, errmsg, strlen(ptr) >= len); + errmsg = apr_psprintf(iter_pool, + "Read data is not equal to expected, EAGAIN" + " inserted at pos: %d, remainder: \"%s\"", + cut, fullmsg + cut); + CuAssertStrnEquals_Msg(tc, errmsg, ptr, len, data); + + ptr += len; + + if (len == 0 && status == APR_EAGAIN) + serf_bucket_mock_more_data_arrived(mock_bkt); + } while(!APR_STATUS_IS_EOF(status)); + + CuAssert(tc, "Read less data than expected.", strlen(ptr) == 0); + } + apr_pool_destroy(iter_pool); + +} + +static void test_dechunk_buckets(CuTest *tc) +{ + serf_bucket_t *mock_bkt, *bkt; + apr_pool_t *test_pool = tc->testBaton; + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, + NULL); + mockbkt_action actions[]= { + /* one chunk */ + { 1, "6" CRLF "blabla" CRLF, APR_SUCCESS }, + /* EAGAIN after first chunk */ + { 1, "6" CRLF "blabla" CRLF, APR_EAGAIN }, + { 1, "6" CRLF "blabla" CRLF, APR_SUCCESS }, + /* CRLF after body split */ + { 1, "6" CRLF "blabla" CR, APR_EAGAIN }, + { 1, LF, APR_SUCCESS }, + /* CRLF before body split */ + { 1, "6" CR, APR_SUCCESS }, + { 1, "", APR_EAGAIN }, + { 1, LF "blabla" CRLF, APR_SUCCESS }, + /* empty chunk */ + { 1, "", APR_SUCCESS }, + /* two chunks */ + { 1, "6" CRLF "blabla" CRLF "6" CRLF "blabla" CRLF, APR_SUCCESS }, + /* three chunks */ + { 1, "6" CRLF "blabla" CRLF "6" CRLF "blabla" CRLF + "0" CRLF "" CRLF, APR_SUCCESS }, + }; + const int nr_of_actions = sizeof(actions) / sizeof(mockbkt_action); + apr_status_t status; + const char *body = "blabla"; + const char *expected = apr_psprintf(test_pool, "%s%s%s%s%s%s%s%s%s", body, + body, body, body, body, body, body, + body, body); + + mock_bkt = serf_bucket_mock_create(actions, nr_of_actions, alloc); + bkt = serf_bucket_dechunk_create(mock_bkt, alloc); + + do + { + const char *data; + apr_size_t len; + + status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len); + CuAssert(tc, "Got error during bucket reading.", + !SERF_BUCKET_READ_ERROR(status)); + CuAssert(tc, "Read more data than expected.", + strlen(expected) >= len); + CuAssert(tc, "Read data is not equal to expected.", + strncmp(expected, data, len) == 0); + + expected += len; + + if (len == 0 && status == APR_EAGAIN) + serf_bucket_mock_more_data_arrived(mock_bkt); + } while(!APR_STATUS_IS_EOF(status)); + + CuAssert(tc, "Read less data than expected.", strlen(expected) == 0); +} + +/* Test that the Content-Length header will be ignored when the response + should not have returned a body. See RFC2616, section 4.4, nbr. 1. */ +static void test_response_no_body_expected(CuTest *tc) +{ + serf_bucket_t *bkt, *tmp; + apr_pool_t *test_pool = tc->testBaton; + char buf[1024]; + apr_size_t len; + serf_bucket_alloc_t *alloc; + int i; + apr_status_t status; + + /* response bucket should consider the blablablablabla as start of the + next response, in all these cases it should APR_EOF after the empty + line. */ + test_server_message_t message_list[] = { + { "HTTP/1.1 100 Continue" CRLF + "Content-Type: text/plain" CRLF + "Content-Length: 6500000" CRLF + CRLF + "blablablablabla" CRLF }, + { "HTTP/1.1 204 No Content" CRLF + "Content-Type: text/plain" CRLF + "Content-Length: 6500000" CRLF + CRLF + "blablablablabla" CRLF }, + { "HTTP/1.1 304 Not Modified" CRLF + "Content-Type: text/plain" CRLF + "Content-Length: 6500000" CRLF + CRLF + "blablablablabla" CRLF }, + }; + + alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); + + /* Test 1: a response to a HEAD request. */ + tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 OK" CRLF + "Content-Type: text/plain" CRLF + "Content-Length: 6500000" CRLF + CRLF + "blablablablabla" CRLF, + alloc); + + bkt = serf_bucket_response_create(tmp, alloc); + serf_bucket_response_set_head(bkt); + + status = read_all(bkt, buf, sizeof(buf), &len); + + CuAssertIntEquals(tc, APR_EOF, status); + CuAssertIntEquals(tc, 0, len); + + /* Test 2: a response with status for which server must not send a body. */ + for (i = 0; i < sizeof(message_list) / sizeof(test_server_message_t); i++) { + + tmp = SERF_BUCKET_SIMPLE_STRING(message_list[i].text, alloc); + bkt = serf_bucket_response_create(tmp, alloc); + + status = read_all(bkt, buf, sizeof(buf), &len); + + CuAssertIntEquals(tc, APR_EOF, status); + CuAssertIntEquals(tc, 0, len); + } } CuSuite *test_buckets(void) { CuSuite *suite = CuSuiteNew(); + CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown); + SUITE_ADD_TEST(suite, test_simple_bucket_readline); SUITE_ADD_TEST(suite, test_response_bucket_read); SUITE_ADD_TEST(suite, test_response_bucket_headers); SUITE_ADD_TEST(suite, test_response_bucket_chunked_read); + SUITE_ADD_TEST(suite, test_response_body_too_small_cl); + SUITE_ADD_TEST(suite, test_response_body_too_small_chunked); + SUITE_ADD_TEST(suite, test_response_body_chunked_no_crlf); + SUITE_ADD_TEST(suite, test_response_body_chunked_incomplete_crlf); + SUITE_ADD_TEST(suite, test_response_body_chunked_gzip_small); + SUITE_ADD_TEST(suite, test_response_bucket_peek_at_headers); SUITE_ADD_TEST(suite, test_bucket_header_set); SUITE_ADD_TEST(suite, test_iovec_buckets); SUITE_ADD_TEST(suite, test_aggregate_buckets); + SUITE_ADD_TEST(suite, test_aggregate_bucket_readline); + SUITE_ADD_TEST(suite, test_header_buckets); + SUITE_ADD_TEST(suite, test_linebuf_crlf_split); + SUITE_ADD_TEST(suite, test_random_eagain_in_response); + SUITE_ADD_TEST(suite, test_dechunk_buckets); + SUITE_ADD_TEST(suite, test_response_no_body_expected); +#if 0 + SUITE_ADD_TEST(suite, test_serf_default_read_iovec); +#endif return suite; } diff -Nru serf-1.1.0/test/test_context.c serf-1.3.3/test/test_context.c --- serf-1.1.0/test/test_context.c 2011-07-12 20:57:16.000000000 +0000 +++ serf-1.3.3/test/test_context.c 2013-11-29 21:22:42.000000000 +0000 @@ -21,127 +21,18 @@ #include #include "serf.h" +#include "serf_private.h" #include "test_serf.h" #include "server/test_server.h" -typedef struct { - serf_response_acceptor_t acceptor; - void *acceptor_baton; - - serf_response_handler_t handler; - - apr_array_header_t *sent_requests; - apr_array_header_t *accepted_requests; - apr_array_header_t *handled_requests; - int req_id; - - const char *method; - const char *path; - int done; - - test_baton_t *tb; -} handler_baton_t; - -static serf_bucket_t* accept_response(serf_request_t *request, - serf_bucket_t *stream, - void *acceptor_baton, - apr_pool_t *pool) -{ - serf_bucket_t *c; - serf_bucket_alloc_t *bkt_alloc; - handler_baton_t *ctx = acceptor_baton; - - /* get the per-request bucket allocator */ - bkt_alloc = serf_request_get_alloc(request); - - /* Create a barrier so the response doesn't eat us! */ - c = serf_bucket_barrier_create(stream, bkt_alloc); - - APR_ARRAY_PUSH(ctx->accepted_requests, int) = ctx->req_id; - - return serf_bucket_response_create(c, bkt_alloc); -} - -static apr_status_t setup_request(serf_request_t *request, - void *setup_baton, - serf_bucket_t **req_bkt, - serf_response_acceptor_t *acceptor, - void **acceptor_baton, - serf_response_handler_t *handler, - void **handler_baton, - apr_pool_t *pool) -{ - handler_baton_t *ctx = setup_baton; - serf_bucket_t *body_bkt; - - /* create a simple body text */ - const char *str = apr_psprintf(pool, "%d", ctx->req_id); - body_bkt = serf_bucket_simple_create(str, strlen(str), NULL, NULL, - serf_request_get_alloc(request)); - *req_bkt = - serf_request_bucket_request_create(request, - ctx->method, ctx->path, - body_bkt, - serf_request_get_alloc(request)); - - APR_ARRAY_PUSH(ctx->sent_requests, int) = ctx->req_id; - - *acceptor = ctx->acceptor; - *acceptor_baton = ctx; - *handler = ctx->handler; - *handler_baton = ctx; - - return APR_SUCCESS; -} - -static apr_status_t handle_response(serf_request_t *request, - serf_bucket_t *response, - void *handler_baton, - apr_pool_t *pool) -{ - handler_baton_t *ctx = handler_baton; - - if (! response) { - serf_connection_request_create(ctx->tb->connection, - setup_request, - ctx); - return APR_SUCCESS; - } - - while (1) { - apr_status_t status; - const char *data; - apr_size_t len; - - status = serf_bucket_read(response, 2048, &data, &len); - if (SERF_BUCKET_READ_ERROR(status)) - return status; - - if (APR_STATUS_IS_EOF(status)) { - APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id; - ctx->done = TRUE; - return APR_EOF; - } - - if (APR_STATUS_IS_EAGAIN(status)) { - return status; - } - - } - - return APR_SUCCESS; -} - /* Validate that requests are sent and completed in the order of creation. */ static void test_serf_connection_request_create(CuTest *tc) { test_baton_t *tb; - serf_request_t *request1, *request2; - handler_baton_t handler_ctx, handler2_ctx; + handler_baton_t handler_ctx[2]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); apr_status_t status; - apr_pool_t *iter_pool; - apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; int i; test_server_message_t message_list[] = { {CHUNKED_REQUEST(1, "1")}, @@ -152,79 +43,33 @@ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, }; - apr_pool_t *test_pool = test_setup(); - accepted_requests = apr_array_make(test_pool, 2, sizeof(int)); - sent_requests = apr_array_make(test_pool, 2, sizeof(int)); - handled_requests = apr_array_make(test_pool, 2, sizeof(int)); + apr_pool_t *test_pool = tc->testBaton; /* Set up a test context with a server */ - status = test_server_setup(&tb, - message_list, 2, - action_list, 2, 0, NULL, - test_pool); + status = test_http_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, NULL, + test_pool); CuAssertIntEquals(tc, APR_SUCCESS, status); - handler_ctx.method = "GET"; - handler_ctx.path = "/"; - handler_ctx.done = FALSE; - - handler_ctx.acceptor = accept_response; - handler_ctx.acceptor_baton = NULL; - handler_ctx.handler = handle_response; - handler_ctx.req_id = 1; - handler_ctx.accepted_requests = accepted_requests; - handler_ctx.sent_requests = sent_requests; - handler_ctx.handled_requests = handled_requests; - - request1 = serf_connection_request_create(tb->connection, - setup_request, - &handler_ctx); - - handler2_ctx = handler_ctx; - handler2_ctx.req_id = 2; - - request2 = serf_connection_request_create(tb->connection, - setup_request, - &handler2_ctx); - - apr_pool_create(&iter_pool, test_pool); - - while (!handler_ctx.done || !handler2_ctx.done) - { - apr_pool_clear(iter_pool); - - status = test_server_run(tb->serv_ctx, 0, iter_pool); - if (APR_STATUS_IS_TIMEUP(status)) - status = APR_SUCCESS; - CuAssertIntEquals(tc, APR_SUCCESS, status); - - status = serf_context_run(tb->context, 0, iter_pool); - if (APR_STATUS_IS_TIMEUP(status)) - status = APR_SUCCESS; - CuAssertIntEquals(tc, APR_SUCCESS, status); - } - apr_pool_destroy(iter_pool); + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + create_new_request(tb, &handler_ctx[1], "GET", "/", 2); - /* Check that all requests were received */ - CuAssertIntEquals(tc, 2, sent_requests->nelts); - CuAssertIntEquals(tc, 2, accepted_requests->nelts); - CuAssertIntEquals(tc, 2, handled_requests->nelts); + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); /* Check that the requests were sent in the order we created them */ - for (i = 0; i < sent_requests->nelts; i++) { - int req_nr = APR_ARRAY_IDX(sent_requests, i, int); + for (i = 0; i < tb->sent_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int); CuAssertIntEquals(tc, i + 1, req_nr); } /* Check that the requests were received in the order we created them */ - for (i = 0; i < handled_requests->nelts; i++) { - int req_nr = APR_ARRAY_IDX(handled_requests, i, int); + for (i = 0; i < tb->handled_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int); CuAssertIntEquals(tc, i + 1, req_nr); } - - test_server_teardown(tb, test_pool); - test_teardown(test_pool); } /* Validate that priority requests are sent and completed before normal @@ -232,11 +77,9 @@ static void test_serf_connection_priority_request_create(CuTest *tc) { test_baton_t *tb; - serf_request_t *request1, *request2, *request3; - handler_baton_t handler_ctx, handler2_ctx, handler3_ctx; + handler_baton_t handler_ctx[3]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); apr_status_t status; - apr_pool_t *iter_pool; - apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; int i; test_server_message_t message_list[] = { @@ -251,99 +94,43 @@ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, }; - apr_pool_t *test_pool = test_setup(); - - accepted_requests = apr_array_make(test_pool, 3, sizeof(int)); - sent_requests = apr_array_make(test_pool, 3, sizeof(int)); - handled_requests = apr_array_make(test_pool, 3, sizeof(int)); - - /* Set up a test context with a server */ - status = test_server_setup(&tb, - message_list, 3, - action_list, 3, 0, NULL, - test_pool); - CuAssertIntEquals(tc, APR_SUCCESS, status); - - handler_ctx.method = "GET"; - handler_ctx.path = "/"; - handler_ctx.done = FALSE; - - handler_ctx.acceptor = accept_response; - handler_ctx.acceptor_baton = NULL; - handler_ctx.handler = handle_response; - handler_ctx.req_id = 2; - handler_ctx.accepted_requests = accepted_requests; - handler_ctx.sent_requests = sent_requests; - handler_ctx.handled_requests = handled_requests; - - request1 = serf_connection_request_create(tb->connection, - setup_request, - &handler_ctx); - - handler2_ctx = handler_ctx; - handler2_ctx.req_id = 3; - - request2 = serf_connection_request_create(tb->connection, - setup_request, - &handler2_ctx); - handler3_ctx = handler_ctx; - handler3_ctx.req_id = 1; - - request3 = serf_connection_priority_request_create(tb->connection, - setup_request, - &handler3_ctx); - - apr_pool_create(&iter_pool, test_pool); - - while (!handler_ctx.done || !handler2_ctx.done || !handler3_ctx.done) - { - apr_pool_clear(iter_pool); - - status = test_server_run(tb->serv_ctx, 0, iter_pool); - if (APR_STATUS_IS_TIMEUP(status)) - status = APR_SUCCESS; - CuAssertIntEquals(tc, APR_SUCCESS, status); + apr_pool_t *test_pool = tc->testBaton; - status = serf_context_run(tb->context, 0, iter_pool); - if (APR_STATUS_IS_TIMEUP(status)) - status = APR_SUCCESS; - CuAssertIntEquals(tc, APR_SUCCESS, status); + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); - /* Debugging purposes only! */ - serf_debug__closed_conn(tb->bkt_alloc); - } - apr_pool_destroy(iter_pool); + create_new_request(tb, &handler_ctx[0], "GET", "/", 2); + create_new_request(tb, &handler_ctx[1], "GET", "/", 3); + create_new_prio_request(tb, &handler_ctx[2], "GET", "/", 1); - /* Check that all requests were received */ - CuAssertIntEquals(tc, 3, sent_requests->nelts); - CuAssertIntEquals(tc, 3, accepted_requests->nelts); - CuAssertIntEquals(tc, 3, handled_requests->nelts); + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); /* Check that the requests were sent in the order we created them */ - for (i = 0; i < sent_requests->nelts; i++) { - int req_nr = APR_ARRAY_IDX(sent_requests, i, int); + for (i = 0; i < tb->sent_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int); CuAssertIntEquals(tc, i + 1, req_nr); } /* Check that the requests were received in the order we created them */ - for (i = 0; i < handled_requests->nelts; i++) { - int req_nr = APR_ARRAY_IDX(handled_requests, i, int); + for (i = 0; i < tb->handled_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int); CuAssertIntEquals(tc, i + 1, req_nr); } - - test_server_teardown(tb, test_pool); - test_teardown(test_pool); } /* Test that serf correctly handles the 'Connection:close' header when the server is planning to close the connection. */ -#define NUM_REQUESTS 10 -static void test_serf_closed_connection(CuTest *tc) +static void test_closed_connection(CuTest *tc) { test_baton_t *tb; - apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; apr_status_t status; - handler_baton_t handler_ctx[NUM_REQUESTS]; + handler_baton_t handler_ctx[10]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); int done = FALSE, i; test_server_message_t message_list[] = { @@ -388,43 +175,24 @@ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, }; - apr_pool_t *test_pool = test_setup(); - - accepted_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int)); - sent_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int)); - handled_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int)); + apr_pool_t *test_pool = tc->testBaton; /* Set up a test context with a server. */ - status = test_server_setup(&tb, - message_list, 10, - action_list, 12, - 0, - NULL, - test_pool); - CuAssertIntEquals(tc, APR_SUCCESS, status); - - for (i = 0 ; i < NUM_REQUESTS ; i++) { - /* Send some requests on the connections */ - handler_ctx[i].method = "GET"; - handler_ctx[i].path = "/"; - handler_ctx[i].done = FALSE; - - handler_ctx[i].acceptor = accept_response; - handler_ctx[i].acceptor_baton = NULL; - handler_ctx[i].handler = handle_response; - handler_ctx[i].req_id = i+1; - handler_ctx[i].accepted_requests = accepted_requests; - handler_ctx[i].sent_requests = sent_requests; - handler_ctx[i].handled_requests = handled_requests; - handler_ctx[i].tb = tb; + status = test_http_server_setup(&tb, + message_list, num_requests, + action_list, 12, + 0, + NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); - serf_connection_request_create(tb->connection, - setup_request, - &handler_ctx[i]); + /* Send some requests on the connections */ + for (i = 0 ; i < num_requests ; i++) { + create_new_request(tb, &handler_ctx[i], "GET", "/", i+1); } while (1) { - status = test_server_run(tb->serv_ctx, 0, test_pool); + status = run_test_server(tb->serv_ctx, 0, test_pool); if (APR_STATUS_IS_TIMEUP(status)) status = APR_SUCCESS; CuAssertIntEquals(tc, APR_SUCCESS, status); @@ -438,7 +206,7 @@ serf_debug__closed_conn(tb->bkt_alloc); done = TRUE; - for (i = 0 ; i < NUM_REQUESTS ; i++) + for (i = 0 ; i < num_requests ; i++) if (handler_ctx[i].done == FALSE) { done = FALSE; break; @@ -447,29 +215,22 @@ break; } - /* Check that all requests were received */ - CuAssertTrue(tc, sent_requests->nelts >= NUM_REQUESTS); - CuAssertIntEquals(tc, NUM_REQUESTS, accepted_requests->nelts); - CuAssertIntEquals(tc, NUM_REQUESTS, handled_requests->nelts); - - /* Cleanup */ - test_server_teardown(tb, test_pool); - test_teardown(test_pool); + /* Check that all requests were received */ + CuAssertTrue(tc, tb->sent_requests->nelts >= num_requests); + CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts); } -#undef NUM_REQUESTS /* Test if serf is sending the request to the proxy, not to the server directly. */ -static void test_serf_setup_proxy(CuTest *tc) +static void test_setup_proxy(CuTest *tc) { test_baton_t *tb; - serf_request_t *request; - handler_baton_t handler_ctx; - apr_status_t status; - apr_pool_t *iter_pool; - apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; int i; - int numrequests = 1; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_pool_t *iter_pool; + apr_status_t status; test_server_message_t message_list[] = { {"GET http://localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\ @@ -486,11 +247,7 @@ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, }; - apr_pool_t *test_pool = test_setup(); - - accepted_requests = apr_array_make(test_pool, numrequests, sizeof(int)); - sent_requests = apr_array_make(test_pool, numrequests, sizeof(int)); - handled_requests = apr_array_make(test_pool, numrequests, sizeof(int)); + apr_pool_t *test_pool = tc->testBaton; /* Set up a test context with a server, no messages expected. */ status = test_server_proxy_setup(&tb, @@ -504,34 +261,20 @@ NULL, test_pool); CuAssertIntEquals(tc, APR_SUCCESS, status); - handler_ctx.method = "GET"; - handler_ctx.path = "/"; - handler_ctx.done = FALSE; - - handler_ctx.acceptor = accept_response; - handler_ctx.acceptor_baton = NULL; - handler_ctx.handler = handle_response; - handler_ctx.req_id = 1; - handler_ctx.accepted_requests = accepted_requests; - handler_ctx.sent_requests = sent_requests; - handler_ctx.handled_requests = handled_requests; - - request = serf_connection_request_create(tb->connection, - setup_request, - &handler_ctx); + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); apr_pool_create(&iter_pool, test_pool); - while (!handler_ctx.done) + while (!handler_ctx[0].done) { apr_pool_clear(iter_pool); - status = test_server_run(tb->serv_ctx, 0, iter_pool); + status = run_test_server(tb->serv_ctx, 0, iter_pool); if (APR_STATUS_IS_TIMEUP(status)) status = APR_SUCCESS; CuAssertIntEquals(tc, APR_SUCCESS, status); - status = test_server_run(tb->proxy_ctx, 0, iter_pool); + status = run_test_server(tb->proxy_ctx, 0, iter_pool); if (APR_STATUS_IS_TIMEUP(status)) status = APR_SUCCESS; CuAssertIntEquals(tc, APR_SUCCESS, status); @@ -547,24 +290,22 @@ apr_pool_destroy(iter_pool); /* Check that all requests were received */ - CuAssertIntEquals(tc, numrequests, sent_requests->nelts); - CuAssertIntEquals(tc, numrequests, accepted_requests->nelts); - CuAssertIntEquals(tc, numrequests, handled_requests->nelts); + CuAssertIntEquals(tc, num_requests, tb->sent_requests->nelts); + CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts); + /* Check that the requests were sent in the order we created them */ - for (i = 0; i < sent_requests->nelts; i++) { - int req_nr = APR_ARRAY_IDX(sent_requests, i, int); + for (i = 0; i < tb->sent_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int); CuAssertIntEquals(tc, i + 1, req_nr); } /* Check that the requests were received in the order we created them */ - for (i = 0; i < handled_requests->nelts; i++) { - int req_nr = APR_ARRAY_IDX(handled_requests, i, int); + for (i = 0; i < tb->handled_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int); CuAssertIntEquals(tc, i + 1, req_nr); } - - test_server_teardown(tb, test_pool); - test_teardown(test_pool); } /***************************************************************************** @@ -617,7 +358,6 @@ static void test_keepalive_limit_one_by_one(CuTest *tc) { test_baton_t *tb; - apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; apr_status_t status; handler_baton_t handler_ctx[SEND_REQUESTS]; int done = FALSE, i; @@ -642,42 +382,24 @@ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, }; - apr_pool_t *test_pool = test_setup(); - - accepted_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int)); - sent_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int)); - handled_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int)); + apr_pool_t *test_pool = tc->testBaton; /* Set up a test context with a server. */ - status = test_server_setup(&tb, - message_list, 7, - action_list, 7, 0, NULL, - test_pool); + status = test_http_server_setup(&tb, + message_list, RCVD_REQUESTS, + action_list, RCVD_REQUESTS, 0, NULL, + test_pool); CuAssertIntEquals(tc, APR_SUCCESS, status); for (i = 0 ; i < SEND_REQUESTS ; i++) { - /* Send some requests on the connections */ - handler_ctx[i].method = "GET"; - handler_ctx[i].path = "/"; - handler_ctx[i].done = FALSE; - - handler_ctx[i].acceptor = accept_response; - handler_ctx[i].acceptor_baton = NULL; - handler_ctx[i].handler = handle_response_keepalive_limit; - handler_ctx[i].req_id = i+1; - handler_ctx[i].accepted_requests = accepted_requests; - handler_ctx[i].sent_requests = sent_requests; - handler_ctx[i].handled_requests = handled_requests; - handler_ctx[i].tb = tb; - - serf_connection_request_create(tb->connection, - setup_request, - &handler_ctx[i]); + create_new_request_with_resp_hdlr(tb, &handler_ctx[i], "GET", "/", i+1, + handle_response_keepalive_limit); + /* TODO: don't think this needs to be done in the loop. */ serf_connection_set_max_outstanding_requests(tb->connection, 1); } while (1) { - status = test_server_run(tb->serv_ctx, 0, test_pool); + status = run_test_server(tb->serv_ctx, 0, test_pool); if (APR_STATUS_IS_TIMEUP(status)) status = APR_SUCCESS; CuAssertIntEquals(tc, APR_SUCCESS, status); @@ -701,13 +423,9 @@ } /* Check that all requests were received */ - CuAssertIntEquals(tc, RCVD_REQUESTS, sent_requests->nelts); - CuAssertIntEquals(tc, RCVD_REQUESTS, accepted_requests->nelts); - CuAssertIntEquals(tc, RCVD_REQUESTS, handled_requests->nelts); - - /* Cleanup */ - test_server_teardown(tb, test_pool); - test_teardown(test_pool); + CuAssertIntEquals(tc, RCVD_REQUESTS, tb->sent_requests->nelts); + CuAssertIntEquals(tc, RCVD_REQUESTS, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, RCVD_REQUESTS, tb->handled_requests->nelts); } #undef SEND_REQUESTS #undef RCVD_REQUESTS @@ -771,8 +489,7 @@ static void test_keepalive_limit_one_by_one_and_burst(CuTest *tc) { test_baton_t *tb; - apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; - apr_status_t status; + apr_status_t status; handler_baton_t handler_ctx[SEND_REQUESTS]; int done = FALSE, i; @@ -796,42 +513,23 @@ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, }; - apr_pool_t *test_pool = test_setup(); - - accepted_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int)); - sent_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int)); - handled_requests = apr_array_make(test_pool, RCVD_REQUESTS, sizeof(int)); + apr_pool_t *test_pool = tc->testBaton; /* Set up a test context with a server. */ - status = test_server_setup(&tb, - message_list, 7, - action_list, 7, 0, NULL, - test_pool); + status = test_http_server_setup(&tb, + message_list, RCVD_REQUESTS, + action_list, RCVD_REQUESTS, 0, NULL, + test_pool); CuAssertIntEquals(tc, APR_SUCCESS, status); for (i = 0 ; i < SEND_REQUESTS ; i++) { - /* Send some requests on the connections */ - handler_ctx[i].method = "GET"; - handler_ctx[i].path = "/"; - handler_ctx[i].done = FALSE; - - handler_ctx[i].acceptor = accept_response; - handler_ctx[i].acceptor_baton = NULL; - handler_ctx[i].handler = handle_response_keepalive_limit_burst; - handler_ctx[i].req_id = i+1; - handler_ctx[i].accepted_requests = accepted_requests; - handler_ctx[i].sent_requests = sent_requests; - handler_ctx[i].handled_requests = handled_requests; - handler_ctx[i].tb = tb; - - serf_connection_request_create(tb->connection, - setup_request, - &handler_ctx[i]); + create_new_request_with_resp_hdlr(tb, &handler_ctx[i], "GET", "/", i+1, + handle_response_keepalive_limit_burst); serf_connection_set_max_outstanding_requests(tb->connection, 1); } while (1) { - status = test_server_run(tb->serv_ctx, 0, test_pool); + status = run_test_server(tb->serv_ctx, 0, test_pool); if (APR_STATUS_IS_TIMEUP(status)) status = APR_SUCCESS; CuAssertIntEquals(tc, APR_SUCCESS, status); @@ -855,18 +553,13 @@ } /* Check that all requests were received */ - CuAssertIntEquals(tc, RCVD_REQUESTS, sent_requests->nelts); - CuAssertIntEquals(tc, RCVD_REQUESTS, accepted_requests->nelts); - CuAssertIntEquals(tc, RCVD_REQUESTS, handled_requests->nelts); - - /* Cleanup */ - test_server_teardown(tb, test_pool); - test_teardown(test_pool); + CuAssertIntEquals(tc, RCVD_REQUESTS, tb->sent_requests->nelts); + CuAssertIntEquals(tc, RCVD_REQUESTS, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, RCVD_REQUESTS, tb->handled_requests->nelts); } #undef SEND_REQUESTS #undef RCVD_REQUESTS -#define NUM_REQUESTS 5 typedef struct { apr_off_t read; apr_off_t written; @@ -893,13 +586,13 @@ return APR_SUCCESS; } -static void test_serf_progress_callback(CuTest *tc) +static void test_progress_callback(CuTest *tc) { test_baton_t *tb; - apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; apr_status_t status; - handler_baton_t handler_ctx[NUM_REQUESTS]; - int done = FALSE, i; + handler_baton_t handler_ctx[5]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + int i; progress_baton_t *pb; test_server_message_t message_list[] = { @@ -918,17 +611,13 @@ {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, }; - apr_pool_t *test_pool = test_setup(); - - accepted_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int)); - sent_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int)); - handled_requests = apr_array_make(test_pool, NUM_REQUESTS, sizeof(int)); - + apr_pool_t *test_pool = tc->testBaton; + /* Set up a test context with a server. */ - status = test_server_setup(&tb, - message_list, 5, - action_list, 5, 0, - progress_conn_setup, test_pool); + status = test_http_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + progress_conn_setup, test_pool); CuAssertIntEquals(tc, APR_SUCCESS, status); /* Set up the progress callback. */ @@ -936,76 +625,1667 @@ tb->user_baton = pb; serf_context_set_progress_cb(tb->context, progress_cb, tb); - for (i = 0 ; i < NUM_REQUESTS ; i++) { - /* Send some requests on the connections */ - handler_ctx[i].method = "GET"; - handler_ctx[i].path = "/"; - handler_ctx[i].done = FALSE; - - handler_ctx[i].acceptor = accept_response; - handler_ctx[i].acceptor_baton = NULL; - handler_ctx[i].handler = handle_response; - handler_ctx[i].req_id = i+1; - handler_ctx[i].accepted_requests = accepted_requests; - handler_ctx[i].sent_requests = sent_requests; - handler_ctx[i].handled_requests = handled_requests; - handler_ctx[i].tb = tb; + /* Send some requests on the connections */ + for (i = 0 ; i < num_requests ; i++) { + create_new_request(tb, &handler_ctx[i], "GET", "/", i+1); + } - serf_connection_request_create(tb->connection, - setup_request, - &handler_ctx[i]); + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); + + /* Check that progress was reported. */ + CuAssertTrue(tc, pb->written > 0); + CuAssertTrue(tc, pb->read > 0); +} + +/* Test that username:password components in url are ignored. */ +static void test_connection_userinfo_in_url(CuTest *tc) +{ + test_baton_t *tb; + apr_status_t status; + handler_baton_t handler_ctx[2]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + int i; + progress_baton_t *pb; + + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + {CHUNKED_REQUEST(1, "2")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + {SERVER_RESPOND, CHUNKED_RESPONSE(1, "2")}, + }; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server. */ + status = test_http_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + progress_conn_setup, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* Create a connection using user:password@hostname syntax */ + tb->serv_url = "http://user:password@localhost:" SERV_PORT_STR; + use_new_connection(tb, test_pool); + + /* Send some requests on the connections */ + for (i = 0 ; i < num_requests ; i++) { + create_new_request(tb, &handler_ctx[i], "GET", "/", i+1); } - while (1) { - status = test_server_run(tb->serv_ctx, 0, test_pool); - if (APR_STATUS_IS_TIMEUP(status)) - status = APR_SUCCESS; - CuAssertIntEquals(tc, APR_SUCCESS, status); + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} - status = serf_context_run(tb->context, 0, test_pool); - if (APR_STATUS_IS_TIMEUP(status)) - status = APR_SUCCESS; - CuAssertIntEquals(tc, APR_SUCCESS, status); +/***************************************************************************** + * Issue #91: test that serf correctly handle an incoming 4xx reponse while + * the outgoing request wasn't written completely yet. + *****************************************************************************/ - /* Debugging purposes only! */ - serf_debug__closed_conn(tb->bkt_alloc); +#define REQUEST_PART1 "PROPFIND / HTTP/1.1" CRLF\ +"Host: lgo-ubuntu.local" CRLF\ +"User-Agent: SVN/1.8.0-dev (x86_64-apple-darwin11.4.2) serf/2.0.0" CRLF\ +"Content-Type: text/xml" CRLF\ +"Transfer-Encoding: chunked" CRLF \ +CRLF\ +"12d" CRLF\ +"" + +#define REQUEST_PART2 \ +""\ +""\ +""\ +"" CRLF\ +"0" CRLF \ +CRLF + +#define RESPONSE_408 "HTTP/1.1 408 Request Time-out" CRLF\ +"Date: Wed, 14 Nov 2012 19:50:35 GMT" CRLF\ +"Server: Apache/2.2.17 (Ubuntu)" CRLF\ +"Vary: Accept-Encoding" CRLF\ +"Content-Length: 305" CRLF\ +"Connection: close" CRLF\ +"Content-Type: text/html; charset=iso-8859-1" CRLF \ +CRLF\ +""\ +"408 Request Time-out

Request Time-out

"\ +"

Server timeout waiting for the HTTP request from the client.


"\ +"
Apache/2.2.17 (Ubuntu) Server at lgo-ubuntu.local Port 80
"\ +"" - done = TRUE; - for (i = 0 ; i < NUM_REQUESTS ; i++) - if (handler_ctx[i].done == FALSE) { - done = FALSE; - break; - } - if (done) - break; + +static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket) +{ + serf_bucket_t *body_bkt; + handler_baton_t *ctx = baton; + + if (ctx->done) { + body_bkt = serf_bucket_simple_create(REQUEST_PART1, strlen(REQUEST_PART2), + NULL, NULL, + ctx->tb->bkt_alloc); + serf_bucket_aggregate_append(aggregate_bucket, body_bkt); } - /* Check that all requests were received */ - CuAssertTrue(tc, sent_requests->nelts >= NUM_REQUESTS); - CuAssertIntEquals(tc, NUM_REQUESTS, accepted_requests->nelts); - CuAssertIntEquals(tc, NUM_REQUESTS, handled_requests->nelts); + return APR_EAGAIN; +} - /* Check that progress was reported. */ - CuAssertTrue(tc, pb->written > 0); - CuAssertTrue(tc, pb->read > 0); +static apr_status_t setup_request_timeout( + serf_request_t *request, + void *setup_baton, + serf_bucket_t **req_bkt, + serf_response_acceptor_t *acceptor, + void **acceptor_baton, + serf_response_handler_t *handler, + void **handler_baton, + apr_pool_t *pool) +{ + handler_baton_t *ctx = setup_baton; + serf_bucket_t *body_bkt; + + *req_bkt = serf__bucket_stream_create(serf_request_get_alloc(request), + detect_eof, + ctx); + + /* create a simple body text */ + body_bkt = serf_bucket_simple_create(REQUEST_PART1, strlen(REQUEST_PART1), + NULL, NULL, + serf_request_get_alloc(request)); + serf_bucket_aggregate_append(*req_bkt, body_bkt); - /* Cleanup */ - test_server_teardown(tb, test_pool); - test_teardown(test_pool); + APR_ARRAY_PUSH(ctx->sent_requests, int) = ctx->req_id; + + *acceptor = ctx->acceptor; + *acceptor_baton = ctx; + *handler = ctx->handler; + *handler_baton = ctx; + + return APR_SUCCESS; } -#undef NUM_REQUESTS -CuSuite *test_context(void) +static apr_status_t handle_response_timeout( + serf_request_t *request, + serf_bucket_t *response, + void *handler_baton, + apr_pool_t *pool) { - CuSuite *suite = CuSuiteNew(); + handler_baton_t *ctx = handler_baton; + serf_status_line sl; + apr_status_t status; + + if (! response) { + serf_connection_request_create(ctx->tb->connection, + setup_request, + ctx); + return APR_SUCCESS; + } + + if (serf_request_is_written(request) != APR_EBUSY) { + return SERF_ERROR_ISSUE_IN_TESTSUITE; + } + + + status = serf_bucket_response_status(response, &sl); + if (SERF_BUCKET_READ_ERROR(status)) { + return status; + } + if (!sl.version && (APR_STATUS_IS_EOF(status) || + APR_STATUS_IS_EAGAIN(status))) { + return status; + } + if (sl.code == 408) { + APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id; + ctx->done = TRUE; + } + + /* discard the rest of the body */ + while (1) { + const char *data; + apr_size_t len; + + status = serf_bucket_read(response, 2048, &data, &len); + if (SERF_BUCKET_READ_ERROR(status) || + APR_STATUS_IS_EAGAIN(status) || + APR_STATUS_IS_EOF(status)) + return status; + } + + return APR_SUCCESS; +} + +static void test_request_timeout(CuTest *tc) +{ + test_baton_t *tb; + apr_status_t status; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + + test_server_message_t message_list[] = { + {REQUEST_PART1}, + {REQUEST_PART2}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, RESPONSE_408}, + }; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server. */ + status = test_http_server_setup(&tb, + message_list, 2, + action_list, 1, 0, + NULL, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* Send some requests on the connection */ + handler_ctx[0].method = "PROPFIND"; + handler_ctx[0].path = "/"; + handler_ctx[0].done = FALSE; + + handler_ctx[0].acceptor = accept_response; + handler_ctx[0].acceptor_baton = NULL; + handler_ctx[0].handler = handle_response_timeout; + handler_ctx[0].req_id = 1; + handler_ctx[0].accepted_requests = tb->accepted_requests; + handler_ctx[0].sent_requests = tb->sent_requests; + handler_ctx[0].handled_requests = tb->handled_requests; + handler_ctx[0].tb = tb; + + serf_connection_request_create(tb->connection, + setup_request_timeout, + &handler_ctx[0]); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} + +static const char *create_large_response_message(apr_pool_t *pool) +{ + const char *response = "HTTP/1.1 200 OK" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF; + struct iovec vecs[500]; + const int num_vecs = 500; + int i, j; + apr_size_t len; + + vecs[0].iov_base = (char *)response; + vecs[0].iov_len = strlen(response); + + for (i = 1; i < num_vecs; i++) + { + int chunk_len = 10 * i * 3; + char *chunk; + char *buf; + + /* end with empty chunk */ + if (i == num_vecs - 1) + chunk_len = 0; + + buf = apr_pcalloc(pool, chunk_len + 1); + for (j = 0; j < chunk_len; j += 10) + memcpy(buf + j, "0123456789", 10); + + chunk = apr_pstrcat(pool, + apr_psprintf(pool, "%x", chunk_len), + CRLF, buf, CRLF, NULL); + vecs[i].iov_base = chunk; + vecs[i].iov_len = strlen(chunk); + } + + return apr_pstrcatv(pool, vecs, num_vecs, &len); +} + +/* Validate reading a large chunked response. */ +static void test_connection_large_response(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + test_server_action_t action_list[1]; + + apr_pool_t *test_pool = tc->testBaton; + + /* create large chunked response message */ + const char *response = create_large_response_message(test_pool); + action_list[0].kind = SERVER_RESPOND; + action_list[0].text = response; + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} + +static const char *create_large_request_message(apr_pool_t *pool) +{ + const char *request = "GET / HTTP/1.1" CRLF + "Host: localhost:12345" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF; + struct iovec vecs[500]; + const int num_vecs = 500; + int i, j; + apr_size_t len; + + vecs[0].iov_base = (char *)request; + vecs[0].iov_len = strlen(request); + + for (i = 1; i < num_vecs; i++) + { + int chunk_len = 10 * i * 3; + char *chunk; + char *buf; + + /* end with empty chunk */ + if (i == num_vecs - 1) + chunk_len = 0; + + buf = apr_pcalloc(pool, chunk_len + 1); + for (j = 0; j < chunk_len; j += 10) + memcpy(buf + j, "0123456789", 10); + + chunk = apr_pstrcat(pool, + apr_psprintf(pool, "%x", chunk_len), + CRLF, buf, CRLF, NULL); + vecs[i].iov_base = chunk; + vecs[i].iov_len = strlen(chunk); + } + + return apr_pstrcatv(pool, vecs, num_vecs, &len); +} + +/* Validate sending a large chunked response. */ +static void test_connection_large_request(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + test_server_message_t message_list[1]; + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + const char *request; + apr_status_t status; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server */ + status = test_http_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, NULL, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* create large chunked request message */ + request = create_large_request_message(test_pool); + message_list[0].text = request; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + handler_ctx[0].request = request; + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} + +/***************************************************************************** + * SSL handshake tests + *****************************************************************************/ +static const char *server_certs[] = { + "test/server/serfservercert.pem", + "test/server/serfcacert.pem", + NULL }; + +static const char *all_server_certs[] = { + "test/server/serfservercert.pem", + "test/server/serfcacert.pem", + "test/server/serfrootcacert.pem", + NULL }; + +static apr_status_t validate_servercert(const serf_ssl_certificate_t *cert, + apr_pool_t *pool) +{ + apr_hash_t *subject; + subject = serf_ssl_cert_subject(cert, pool); + if (strcmp("localhost", + apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Test Suite Server", + apr_hash_get(subject, "OU", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("In Serf we trust, Inc.", + apr_hash_get(subject, "O", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Mechelen", + apr_hash_get(subject, "L", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Antwerp", + apr_hash_get(subject, "ST", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("BE", + apr_hash_get(subject, "C", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("serfserver@example.com", + apr_hash_get(subject, "E", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + return APR_SUCCESS; +} + +static apr_status_t validate_cacert(const serf_ssl_certificate_t *cert, + apr_pool_t *pool) +{ + apr_hash_t *subject; + subject = serf_ssl_cert_subject(cert, pool); + if (strcmp("Serf CA", + apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Test Suite CA", + apr_hash_get(subject, "OU", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("In Serf we trust, Inc.", + apr_hash_get(subject, "O", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Mechelen", + apr_hash_get(subject, "L", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Antwerp", + apr_hash_get(subject, "ST", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("BE", + apr_hash_get(subject, "C", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("serfca@example.com", + apr_hash_get(subject, "E", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + return APR_SUCCESS; +} + +static apr_status_t validate_rootcacert(const serf_ssl_certificate_t *cert, + apr_pool_t *pool) +{ + apr_hash_t *subject; + subject = serf_ssl_cert_subject(cert, pool); + if (strcmp("Serf Root CA", + apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Test Suite Root CA", + apr_hash_get(subject, "OU", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("In Serf we trust, Inc.", + apr_hash_get(subject, "O", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Mechelen", + apr_hash_get(subject, "L", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Antwerp", + apr_hash_get(subject, "ST", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("BE", + apr_hash_get(subject, "C", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("serfrootca@example.com", + apr_hash_get(subject, "E", APR_HASH_KEY_STRING)) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + return APR_SUCCESS; +} + +static apr_status_t +ssl_server_cert_cb_expect_failures(void *baton, int failures, + const serf_ssl_certificate_t *cert) +{ + test_baton_t *tb = baton; + int expected_failures = *(int *)tb->user_baton; + + tb->result_flags |= TEST_RESULT_SERVERCERTCB_CALLED; + + /* We expect an error from the certificate validation function. */ + if (failures & expected_failures) + return APR_SUCCESS; + else + return SERF_ERROR_ISSUE_IN_TESTSUITE; +} + +static apr_status_t +ssl_server_cert_cb_expect_allok(void *baton, int failures, + const serf_ssl_certificate_t *cert) +{ + test_baton_t *tb = baton; + tb->result_flags |= TEST_RESULT_SERVERCERTCB_CALLED; + + /* No error expected, certificate is valid. */ + if (failures) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + else + return APR_SUCCESS; +} + +static apr_status_t +ssl_server_cert_cb_reject(void *baton, int failures, + const serf_ssl_certificate_t *cert) +{ + return SERF_ERROR_ISSUE_IN_TESTSUITE; +} + +/* Validate that we can connect successfully to an https server. This + certificate is not trusted, so a cert validation failure is expected. */ +static void test_ssl_handshake(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + int expected_failures; + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + static const char *server_cert[] = { "test/server/serfservercert.pem", + NULL }; + + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + NULL, /* default conn setup */ + "test/server/serfserverkey.pem", + server_cert, + NULL, /* no client cert */ + ssl_server_cert_cb_expect_failures, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* This unknown failures is X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, + meaning the chain has only the server cert. A good candidate for its + own failure code. */ + expected_failures = SERF_SSL_CERT_UNKNOWNCA; + tb->user_baton = &expected_failures; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} + +/* Set up the ssl context with the CA and root CA certificates needed for + successful valiation of the server certificate. */ +static apr_status_t +https_set_root_ca_conn_setup(apr_socket_t *skt, + serf_bucket_t **input_bkt, + serf_bucket_t **output_bkt, + void *setup_baton, + apr_pool_t *pool) +{ + serf_ssl_certificate_t *rootcacert; + test_baton_t *tb = setup_baton; + apr_status_t status; + + status = default_https_conn_setup(skt, input_bkt, output_bkt, + setup_baton, pool); + if (status) + return status; + + status = serf_ssl_load_cert_file(&rootcacert, + "test/server/serfrootcacert.pem", + pool); + if (status) + return status; + status = serf_ssl_trust_cert(tb->ssl_context, rootcacert); + if (status) + return status; + + return status; +} + +/* Validate that server certificate validation is ok when we + explicitly trust our self-signed root ca. */ +static void test_ssl_trust_rootca(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + ssl_server_cert_cb_expect_allok, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} + +/* Validate that when the application rejects the cert, the context loop + bails out with an error. */ +static void test_ssl_application_rejects_cert(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + /* The certificate is valid, but we tell serf to reject it. */ + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + ssl_server_cert_cb_reject, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + status = test_helper_run_requests_no_check(tc, tb, num_requests, + handler_ctx, test_pool); + /* We expect an error from the certificate validation function. */ + CuAssert(tc, "Application told serf the certificate should be rejected," + " expected error!", status != APR_SUCCESS); +} + +/* Test for ssl certificate chain callback. */ +static apr_status_t +cert_chain_cb(void *baton, + int failures, + int error_depth, + const serf_ssl_certificate_t * const * certs, + apr_size_t certs_len) +{ + test_baton_t *tb = baton; + apr_status_t status; + + tb->result_flags |= TEST_RESULT_SERVERCERTCHAINCB_CALLED; + + if (failures) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + if (certs_len != 3) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + status = validate_rootcacert(certs[2], tb->pool); + if (status) + return status; + + status = validate_cacert(certs[1], tb->pool); + if (status) + return status; + + status = validate_servercert(certs[0], tb->pool); + if (status) + return status; + + return APR_SUCCESS; +} + +static apr_status_t +chain_rootca_callback_conn_setup(apr_socket_t *skt, + serf_bucket_t **input_bkt, + serf_bucket_t **output_bkt, + void *setup_baton, + apr_pool_t *pool) +{ + test_baton_t *tb = setup_baton; + apr_status_t status; + + status = https_set_root_ca_conn_setup(skt, input_bkt, output_bkt, + setup_baton, pool); + if (status) + return status; + + serf_ssl_server_cert_chain_callback_set(tb->ssl_context, + ssl_server_cert_cb_expect_allok, + cert_chain_cb, + tb); + + return APR_SUCCESS; +} + +/* Make the server return a partial certificate chain (server cert, CA cert), + the root CA cert is trusted explicitly in the client. Test the chain + callback. */ +static void test_ssl_certificate_chain_with_anchor(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + chain_rootca_callback_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + ssl_server_cert_cb_expect_allok, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCB_CALLED); + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCHAINCB_CALLED); +} + +static apr_status_t +cert_chain_all_certs_cb(void *baton, + int failures, + int error_depth, + const serf_ssl_certificate_t * const * certs, + apr_size_t certs_len) +{ + /* Root CA cert is selfsigned, ignore this 'failure'. */ + failures &= ~SERF_SSL_CERT_SELF_SIGNED; + + return cert_chain_cb(baton, failures, error_depth, certs, certs_len); +} + +static apr_status_t +chain_callback_conn_setup(apr_socket_t *skt, + serf_bucket_t **input_bkt, + serf_bucket_t **output_bkt, + void *setup_baton, + apr_pool_t *pool) +{ + test_baton_t *tb = setup_baton; + apr_status_t status; + + status = default_https_conn_setup(skt, input_bkt, output_bkt, + setup_baton, pool); + if (status) + return status; + + serf_ssl_server_cert_chain_callback_set(tb->ssl_context, + ssl_server_cert_cb_expect_allok, + cert_chain_all_certs_cb, + tb); + + return APR_SUCCESS; +} + +/* Make the server return the complete certificate chain (server cert, CA cert + and root CA cert). Test the chain callback. */ +static void test_ssl_certificate_chain_all_from_server(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + chain_callback_conn_setup, + "test/server/serfserverkey.pem", + all_server_certs, + NULL, /* no client cert */ + ssl_server_cert_cb_expect_allok, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCB_CALLED); + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCHAINCB_CALLED); +} + +/* Validate that the ssl handshake succeeds if no application callbacks + are set, and the ssl server certificate chains is ok. */ +static void test_ssl_no_servercert_callback_allok(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + apr_status_t status; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); +} + +/* Validate that the ssl handshake fails if no application callbacks + are set, and the ssl server certificate chains is NOT ok. */ +static void test_ssl_no_servercert_callback_fail(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + apr_status_t status; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + NULL, /* default conn setup, no certs */ + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + status = test_helper_run_requests_no_check(tc, tb, num_requests, + handler_ctx, test_pool); + /* We expect an error from the certificate validation function. */ + CuAssertIntEquals(tc, SERF_ERROR_SSL_CERT_FAILED, status); +} + +/* Similar to test_connection_large_response, validate reading a large + chunked response over SSL. */ +static void test_ssl_large_response(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + test_server_action_t action_list[1]; + apr_status_t status; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + const char *response; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* create large chunked response message */ + response = create_large_response_message(test_pool); + action_list[0].kind = SERVER_RESPOND; + action_list[0].text = response; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); +} + +/* Similar to test_connection_large_request, validate sending a large + chunked request over SSL. */ +static void test_ssl_large_request(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + test_server_message_t message_list[1]; + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + const char *request; + apr_status_t status; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* create large chunked request message */ + request = create_large_request_message(test_pool); + message_list[0].text = request; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + handler_ctx[0].request = request; + + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); +} + +static apr_status_t client_cert_cb(void *data, const char **cert_path) +{ + test_baton_t *tb = data; + + tb->result_flags |= TEST_RESULT_CLIENT_CERTCB_CALLED; + + *cert_path = "test/server/serfclientcert.p12"; + + return APR_SUCCESS; +} + +static apr_status_t client_cert_pw_cb(void *data, + const char *cert_path, + const char **password) +{ + test_baton_t *tb = data; + + tb->result_flags |= TEST_RESULT_CLIENT_CERTPWCB_CALLED; + + if (strcmp(cert_path, "test/server/serfclientcert.p12") == 0) + { + *password = "serftest"; + return APR_SUCCESS; + } + + return SERF_ERROR_ISSUE_IN_TESTSUITE; +} + +static apr_status_t +client_cert_conn_setup(apr_socket_t *skt, + serf_bucket_t **input_bkt, + serf_bucket_t **output_bkt, + void *setup_baton, + apr_pool_t *pool) +{ + test_baton_t *tb = setup_baton; + apr_status_t status; + + status = https_set_root_ca_conn_setup(skt, input_bkt, output_bkt, + setup_baton, pool); + if (status) + return status; + + serf_ssl_client_cert_provider_set(tb->ssl_context, + client_cert_cb, + tb, + pool); + + serf_ssl_client_cert_password_set(tb->ssl_context, + client_cert_pw_cb, + tb, + pool); + + return APR_SUCCESS; +} + +static void test_ssl_client_certificate(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + apr_status_t status; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + /* The SSL server the complete certificate chain to validate the client + certificate. */ + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + client_cert_conn_setup, + "test/server/serfserverkey.pem", + all_server_certs, + "Serf Client", + NULL, /* No server cert callback */ + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_CLIENT_CERTCB_CALLED); + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_CLIENT_CERTPWCB_CALLED); +} + +/* Validate that the expired certificate is reported as failure in the + callback. */ +static void test_ssl_expired_server_cert(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + int expected_failures; + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + static const char *expired_server_certs[] = { + "test/server/serfserver_expired_cert.pem", + "test/server/serfcacert.pem", + "test/server/serfrootcacert.pem", + NULL }; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + NULL, /* default conn setup */ + "test/server/serfserverkey.pem", + expired_server_certs, + NULL, /* no client cert */ + ssl_server_cert_cb_expect_failures, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + expected_failures = SERF_SSL_CERT_SELF_SIGNED | + SERF_SSL_CERT_EXPIRED; + tb->user_baton = &expected_failures; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} + +/* Validate that the expired certificate is reported as failure in the + callback. */ +static void test_ssl_future_server_cert(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + int expected_failures; + apr_status_t status; + test_server_message_t message_list[] = { + {CHUNKED_REQUEST(1, "1")}, + }; + + test_server_action_t action_list[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + static const char *future_server_certs[] = { + "test/server/serfserver_future_cert.pem", + "test/server/serfcacert.pem", + "test/server/serfrootcacert.pem", + NULL }; + + /* Set up a test context with a server */ + apr_pool_t *test_pool = tc->testBaton; + + status = test_https_server_setup(&tb, + message_list, num_requests, + action_list, num_requests, 0, + NULL, /* default conn setup */ + "test/server/serfserverkey.pem", + future_server_certs, + NULL, /* no client cert */ + ssl_server_cert_cb_expect_failures, + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + expected_failures = SERF_SSL_CERT_SELF_SIGNED | + SERF_SSL_CERT_NOTYETVALID; + tb->user_baton = &expected_failures; + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} + + +/* Test if serf is sets up an SSL tunnel to the proxy and doesn't contact the + https server directly. */ +static void test_setup_ssltunnel(CuTest *tc) +{ + test_baton_t *tb; + int i; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + + /* TODO: issue 83: should be relative uri instead of absolute. */ + test_server_message_t message_list_server[] = { + {"GET / HTTP/1.1" CRLF\ + "Host: localhost:" SERV_PORT_STR CRLF\ + "Transfer-Encoding: chunked" CRLF\ + CRLF\ + "1" CRLF\ + "1" CRLF\ + "0" CRLF\ + CRLF} + }; + test_server_action_t action_list_server[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + test_server_message_t message_list_proxy[] = { + {"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\ + "Host: localhost:" SERV_PORT_STR CRLF\ + CRLF }, + { NULL } + }; + test_server_action_t action_list_proxy[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + /* Forward the remainder of the data to the server without validation */ + {PROXY_FORWARD, "https://localhost:" SERV_PORT_STR}, + }; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server and a proxy. Serf should send a + CONNECT request to the server. */ + status = test_https_server_proxy_setup(&tb, + /* server messages and actions */ + message_list_server, 1, + action_list_server, 1, + /* proxy messages and actions */ + message_list_proxy, 2, + action_list_proxy, 2, + 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + + CuAssertIntEquals(tc, APR_SUCCESS, status); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); + + /* Check that the requests were sent in the order we created them */ + for (i = 0; i < tb->sent_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int); + CuAssertIntEquals(tc, i + 1, req_nr); + } + + /* Check that the requests were received in the order we created them */ + for (i = 0; i < tb->handled_requests->nelts; i++) { + int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int); + CuAssertIntEquals(tc, i + 1, req_nr); + } +} + +/* Test error if no creds callback */ +static void test_ssltunnel_no_creds_cb(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + + test_server_message_t message_list_proxy[] = { + {"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\ + "Host: localhost:" SERV_PORT_STR CRLF\ + CRLF }, + }; + test_server_action_t action_list_proxy[] = { + {SERVER_RESPOND, "HTTP/1.1 407 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF + CRLF + "1" CRLF CRLF + "0" CRLF CRLF}, + }; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server and a proxy. Serf should send a + CONNECT request to the server. */ + status = test_https_server_proxy_setup(&tb, + /* server messages and actions */ + NULL, 0, + NULL, 0, + /* proxy messages and actions */ + message_list_proxy, 1, + action_list_proxy, 1, + 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* No credentials callback configured. */ + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + status = test_helper_run_requests_no_check(tc, tb, num_requests, + handler_ctx, test_pool); + CuAssertIntEquals(tc, SERF_ERROR_SSLTUNNEL_SETUP_FAILED, status); +} + +static apr_status_t +ssltunnel_basic_authn_callback(char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) +{ + handler_baton_t *handler_ctx = baton; + test_baton_t *tb = handler_ctx->tb; + + serf__log(TEST_VERBOSE, __FILE__, "ssltunnel_basic_authn_callback\n"); + + tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; + + if (strcmp("Basic", authn_type) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + if (code == 401) { + if (strcmp(" Test Suite", realm) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + *username = "serf"; + *password = "serftest"; + } + else if (code == 407) { + if (strcmp(" Test Suite Proxy", realm) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + *username = "serfproxy"; + *password = "serftest"; + } else + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + serf__log(TEST_VERBOSE, __FILE__, "ssltunnel_basic_authn_callback finished successfully.\n"); + + return APR_SUCCESS; +} + +/* Test if serf can successfully authenticate to a proxy used for an ssl + tunnel. Retry the authentication a few times to test requeueing of the + CONNECT request. */ +static void ssltunnel_basic_auth(CuTest *tc, const char *server_resp_hdrs, + const char *proxy_resp_hdrs) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + int num_requests_sent, num_requests_recvd; + test_server_message_t message_list_server[2]; + test_server_action_t action_list_proxy[7]; + test_server_action_t action_list_server[2]; + apr_pool_t *test_pool = tc->testBaton; + apr_status_t status; + + test_server_message_t message_list_proxy[] = { + {"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF + "Host: localhost:" SERV_PORT_STR CRLF + CRLF }, + {"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF + "Host: localhost:" SERV_PORT_STR CRLF + "Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF + CRLF }, + {"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF + "Host: localhost:" SERV_PORT_STR CRLF + "Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF + CRLF }, + {"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF + "Host: localhost:" SERV_PORT_STR CRLF + "Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF + CRLF }, + {"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF + "Host: localhost:" SERV_PORT_STR CRLF + "Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF + CRLF }, + }; + + action_list_proxy[0].kind = SERVER_RESPOND; + action_list_proxy[0].text = apr_psprintf(test_pool, + "HTTP/1.1 407 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF + "%s" + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, proxy_resp_hdrs); + action_list_proxy[1].kind = SERVER_RESPOND; + action_list_proxy[1].text = apr_psprintf(test_pool, + "HTTP/1.1 407 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF + "%s" + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, proxy_resp_hdrs); + + action_list_proxy[2].kind = SERVER_RESPOND; + action_list_proxy[2].text = apr_psprintf(test_pool, + "HTTP/1.1 407 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF + "%s" + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, proxy_resp_hdrs); + + action_list_proxy[3].kind = SERVER_RESPOND; + action_list_proxy[3].text = CHUNKED_EMPTY_RESPONSE; + /* Forward the remainder of the data to the server without validation */ + action_list_proxy[4].kind = PROXY_FORWARD; + action_list_proxy[4].text = "https://localhost:" SERV_PORT_STR; + /* If the client or the server closes the connection, stop forwarding.*/ + action_list_proxy[5].kind = SERVER_RESPOND; + action_list_proxy[5].text = CHUNKED_EMPTY_RESPONSE; + /* Again after disconnect. */ + action_list_proxy[6].kind = PROXY_FORWARD; + action_list_proxy[6].text = "https://localhost:" SERV_PORT_STR; + + /* Make the server also require Basic authentication */ + message_list_server[0].text = + "GET / HTTP/1.1" CRLF + "Host: localhost:" SERV_PORT_STR CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "1" CRLF + "0" CRLF + CRLF; + message_list_server[1].text = + "GET / HTTP/1.1" CRLF + "Host: localhost:" SERV_PORT_STR CRLF + "Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF + "Transfer-Encoding: chunked" CRLF + CRLF + "1" CRLF + "1" CRLF + "0" CRLF + CRLF; + + action_list_server[0].kind = SERVER_RESPOND; + action_list_server[0].text = apr_psprintf(test_pool, + "HTTP/1.1 401 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "WWW-Authenticate: Basic realm=""Test Suite""" CRLF + "%s" + CRLF + "1" CRLF CRLF + "0" CRLF CRLF, server_resp_hdrs); + action_list_server[1].kind = SERVER_RESPOND; + action_list_server[1].text = CHUNKED_EMPTY_RESPONSE; + + /* Set up a test context with a server and a proxy. Serf should send a + CONNECT request to the server. */ + status = test_https_server_proxy_setup(&tb, + /* server messages and actions */ + message_list_server, 2, + action_list_server, 2, + /* proxy messages and actions */ + message_list_proxy, 5, + action_list_proxy, 7, + 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + + CuAssertIntEquals(tc, APR_SUCCESS, status); + + serf_config_authn_types(tb->context, SERF_AUTHN_BASIC); + serf_config_credentials_callback(tb->context, ssltunnel_basic_authn_callback); + + create_new_request(tb, &handler_ctx[0], "GET", "/", 1); + + /* Test that a request is retried and authentication headers are set + correctly. */ + num_requests_sent = 1; + num_requests_recvd = 2; + + status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, + handler_ctx, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); + CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); +} + +static void test_ssltunnel_basic_auth(CuTest *tc) +{ + /* KeepAlive On for both proxy and server */ + ssltunnel_basic_auth(tc, "", ""); +} + +static void test_ssltunnel_basic_auth_server_has_keepalive_off(CuTest *tc) +{ + /* Add Connection:Close header to server response */ + ssltunnel_basic_auth(tc, "Connection: close" CRLF, ""); +} + +static void test_ssltunnel_basic_auth_proxy_has_keepalive_off(CuTest *tc) +{ + /* Add Connection:Close header to proxy response */ + ssltunnel_basic_auth(tc, "", "Connection: close" CRLF); +} + +static apr_status_t +proxy_digest_authn_callback(char **username, + char **password, + serf_request_t *request, void *baton, + int code, const char *authn_type, + const char *realm, + apr_pool_t *pool) +{ + handler_baton_t *handler_ctx = baton; + test_baton_t *tb = handler_ctx->tb; + + tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; + + if (code != 407) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp("Digest", authn_type) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + if (strcmp(" Test Suite Proxy", realm) != 0) + return SERF_ERROR_ISSUE_IN_TESTSUITE; + + *username = "serf"; + *password = "serftest"; + + return APR_SUCCESS; +} + +/* Test if serf can successfully authenticate to a proxy used for an ssl + tunnel. */ +static void test_ssltunnel_digest_auth(CuTest *tc) +{ + test_baton_t *tb; + handler_baton_t handler_ctx[1]; + const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]); + apr_status_t status; + + test_server_message_t message_list_server[] = { + {"GET /test/index.html HTTP/1.1" CRLF\ + "Host: localhost:" SERV_PORT_STR CRLF\ + "Transfer-Encoding: chunked" CRLF\ + CRLF\ + "1" CRLF\ + "1" CRLF\ + "0" CRLF\ + CRLF} + }; + test_server_action_t action_list_server[] = { + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + }; + +#define CONNECT_REQ\ + "CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\ + "Host: localhost:" SERV_PORT_STR CRLF + + test_server_message_t message_list_proxy[] = { + { CONNECT_REQ CRLF }, + { CONNECT_REQ + "Proxy-Authorization: Digest realm=\"Test Suite Proxy\", " + "username=\"serf\", " + "nonce=\"ABCDEF1234567890\", uri=\"localhost:" SERV_PORT_STR "\", " + "response=\"15b1841822273b0fd44d2f6457f64213\", opaque=\"myopaque\", " + "algorithm=\"MD5\"" CRLF + CRLF }, + }; + /* Add a Basic header before Digest header, to test that serf uses the most + secure authentication scheme first, instead of following the order of + the headers. */ + /* Use non standard case for Proxy-Authenticate header to test case + insensitivity for http headers. */ + test_server_action_t action_list_proxy[] = { + {SERVER_RESPOND, "HTTP/1.1 407 Unauthorized" CRLF + "Transfer-Encoding: chunked" CRLF + "Proxy-Authenticate: Basic c2VyZjpzZXJmdGVzdA==" CRLF + "Proxy-Authenticate: NonExistent blablablabla" CRLF + "proXy-Authenticate: Digest realm=\"Test Suite Proxy\"," + "nonce=\"ABCDEF1234567890\",opaque=\"myopaque\"," + "algorithm=\"MD5\",qop-options=\"auth\"" CRLF + CRLF + "1" CRLF CRLF + "0" CRLF CRLF}, + {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE}, + /* Forward the remainder of the data to the server without validation */ + {PROXY_FORWARD, "https://localhost:" SERV_PORT_STR}, + }; + + apr_pool_t *test_pool = tc->testBaton; + + /* Set up a test context with a server and a proxy. Serf should send a + CONNECT request to the server. */ + status = test_https_server_proxy_setup(&tb, + /* server messages and actions */ + message_list_server, 1, + action_list_server, 1, + /* proxy messages and actions */ + message_list_proxy, 2, + action_list_proxy, 3, + 0, + https_set_root_ca_conn_setup, + "test/server/serfserverkey.pem", + server_certs, + NULL, /* no client cert */ + NULL, /* No server cert callback */ + test_pool); + + CuAssertIntEquals(tc, APR_SUCCESS, status); + + serf_config_authn_types(tb->context, SERF_AUTHN_BASIC | SERF_AUTHN_DIGEST); + serf_config_credentials_callback(tb->context, proxy_digest_authn_callback); + + create_new_request(tb, &handler_ctx[0], "GET", "/test/index.html", 1); + test_helper_run_requests_expect_ok(tc, tb, num_requests, + handler_ctx, test_pool); + + CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); +} + +/*****************************************************************************/ +CuSuite *test_context(void) +{ + CuSuite *suite = CuSuiteNew(); + + CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown); SUITE_ADD_TEST(suite, test_serf_connection_request_create); SUITE_ADD_TEST(suite, test_serf_connection_priority_request_create); - SUITE_ADD_TEST(suite, test_serf_closed_connection); - SUITE_ADD_TEST(suite, test_serf_setup_proxy); + SUITE_ADD_TEST(suite, test_closed_connection); + SUITE_ADD_TEST(suite, test_setup_proxy); SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one); SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one_and_burst); - SUITE_ADD_TEST(suite, test_serf_progress_callback); + SUITE_ADD_TEST(suite, test_progress_callback); + SUITE_ADD_TEST(suite, test_request_timeout); + SUITE_ADD_TEST(suite, test_connection_large_response); + SUITE_ADD_TEST(suite, test_connection_large_request); + SUITE_ADD_TEST(suite, test_connection_userinfo_in_url); + SUITE_ADD_TEST(suite, test_ssl_handshake); + SUITE_ADD_TEST(suite, test_ssl_trust_rootca); + SUITE_ADD_TEST(suite, test_ssl_application_rejects_cert); + SUITE_ADD_TEST(suite, test_ssl_certificate_chain_with_anchor); + SUITE_ADD_TEST(suite, test_ssl_certificate_chain_all_from_server); + SUITE_ADD_TEST(suite, test_ssl_no_servercert_callback_allok); + SUITE_ADD_TEST(suite, test_ssl_no_servercert_callback_fail); + SUITE_ADD_TEST(suite, test_ssl_large_response); + SUITE_ADD_TEST(suite, test_ssl_large_request); + SUITE_ADD_TEST(suite, test_ssl_client_certificate); + SUITE_ADD_TEST(suite, test_ssl_expired_server_cert); + SUITE_ADD_TEST(suite, test_ssl_future_server_cert); + SUITE_ADD_TEST(suite, test_setup_ssltunnel); + SUITE_ADD_TEST(suite, test_ssltunnel_no_creds_cb); + SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth); + SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_server_has_keepalive_off); + SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_proxy_has_keepalive_off); + SUITE_ADD_TEST(suite, test_ssltunnel_digest_auth); return suite; } diff -Nru serf-1.1.0/test/test_serf.h serf-1.3.3/test/test_serf.h --- serf-1.1.0/test/test_serf.h 2011-07-13 03:22:01.000000000 +0000 +++ serf-1.3.3/test/test_serf.h 2013-06-23 08:43:58.000000000 +0000 @@ -45,10 +45,13 @@ CuSuite *test_context(void); CuSuite *test_buckets(void); CuSuite *test_ssl(void); +CuSuite *test_auth(void); +CuSuite *test_mock_bucket(void); /* Test setup declarations */ - #define CRLF "\r\n" +#define CR "\r" +#define LF "\n" #define CHUNKED_REQUEST(len, body)\ "GET / HTTP/1.1" CRLF\ @@ -60,6 +63,16 @@ "0" CRLF\ CRLF +#define CHUNKED_REQUEST_URI(uri, len, body)\ + "GET " uri " HTTP/1.1" CRLF\ + "Host: localhost:12345" CRLF\ + "Transfer-Encoding: chunked" CRLF\ + CRLF\ + #len CRLF\ + body CRLF\ + "0" CRLF\ + CRLF + #define CHUNKED_RESPONSE(len, body)\ "HTTP/1.1 200 OK" CRLF\ "Transfer-Encoding: chunked" CRLF\ @@ -90,19 +103,54 @@ serv_ctx_t *proxy_ctx; apr_sockaddr_t *proxy_addr; + /* Cache connection params here so it gets user for a test to switch to a + new connection. */ + const char *serv_url; + serf_connection_setup_t conn_setup; + /* An extra baton which can be freely used by tests. */ void *user_baton; + /* Flags that can be used to report situations, e.g. that a callback was + called. */ + int result_flags; + + apr_array_header_t *accepted_requests, *handled_requests, *sent_requests; + + serf_ssl_context_t *ssl_context; + serf_ssl_need_server_cert_t server_cert_cb; } test_baton_t; -apr_status_t test_server_setup(test_baton_t **tb_p, - test_server_message_t *message_list, - apr_size_t message_count, - test_server_action_t *action_list, - apr_size_t action_count, - apr_int32_t options, - serf_connection_setup_t conn_setup, - apr_pool_t *pool); +apr_status_t default_https_conn_setup(apr_socket_t *skt, + serf_bucket_t **input_bkt, + serf_bucket_t **output_bkt, + void *setup_baton, + apr_pool_t *pool); + +apr_status_t use_new_connection(test_baton_t *tb, + apr_pool_t *pool); + +apr_status_t test_https_server_setup(test_baton_t **tb_p, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + serf_connection_setup_t conn_setup, + const char *keyfile, + const char **certfile, + const char *client_cn, + serf_ssl_need_server_cert_t server_cert_cb, + apr_pool_t *pool); + +apr_status_t test_http_server_setup(test_baton_t **tb_p, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + serf_connection_setup_t conn_setup, + apr_pool_t *pool); apr_status_t test_server_proxy_setup( test_baton_t **tb_p, @@ -118,9 +166,119 @@ serf_connection_setup_t conn_setup, apr_pool_t *pool); -apr_status_t test_server_teardown(test_baton_t *tb, apr_pool_t *pool); +apr_status_t test_https_server_proxy_setup( + test_baton_t **tb_p, + test_server_message_t *serv_message_list, + apr_size_t serv_message_count, + test_server_action_t *serv_action_list, + apr_size_t serv_action_count, + test_server_message_t *proxy_message_list, + apr_size_t proxy_message_count, + test_server_action_t *proxy_action_list, + apr_size_t proxy_action_count, + apr_int32_t options, + serf_connection_setup_t conn_setup, + const char *keyfile, + const char **certfiles, + const char *client_cn, + serf_ssl_need_server_cert_t server_cert_cb, + apr_pool_t *pool); + +void *test_setup(void *baton); +void *test_teardown(void *baton); + +typedef struct { + serf_response_acceptor_t acceptor; + void *acceptor_baton; + + serf_response_handler_t handler; + + apr_array_header_t *sent_requests; + apr_array_header_t *accepted_requests; + apr_array_header_t *handled_requests; + int req_id; + + const char *method; + const char *path; + /* Use this for a raw request message */ + const char *request; + int done; + + test_baton_t *tb; +} handler_baton_t; + +/* These defines are used with the test_baton_t result_flags variable. */ +#define TEST_RESULT_SERVERCERTCB_CALLED 0x0001 +#define TEST_RESULT_SERVERCERTCHAINCB_CALLED 0x0002 +#define TEST_RESULT_CLIENT_CERTCB_CALLED 0x0004 +#define TEST_RESULT_CLIENT_CERTPWCB_CALLED 0x0008 +#define TEST_RESULT_AUTHNCB_CALLED 0x001A + +apr_status_t +test_helper_run_requests_no_check(CuTest *tc, test_baton_t *tb, + int num_requests, + handler_baton_t handler_ctx[], + apr_pool_t *pool); +void +test_helper_run_requests_expect_ok(CuTest *tc, test_baton_t *tb, + int num_requests, + handler_baton_t handler_ctx[], + apr_pool_t *pool); +serf_bucket_t* accept_response(serf_request_t *request, + serf_bucket_t *stream, + void *acceptor_baton, + apr_pool_t *pool); +apr_status_t setup_request(serf_request_t *request, + void *setup_baton, + serf_bucket_t **req_bkt, + serf_response_acceptor_t *acceptor, + void **acceptor_baton, + serf_response_handler_t *handler, + void **handler_baton, + apr_pool_t *pool); +apr_status_t handle_response(serf_request_t *request, + serf_bucket_t *response, + void *handler_baton, + apr_pool_t *pool); +void setup_handler(test_baton_t *tb, handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id, + serf_response_handler_t handler); +void create_new_prio_request(test_baton_t *tb, + handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id); +void create_new_request(test_baton_t *tb, + handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id); +void +create_new_request_with_resp_hdlr(test_baton_t *tb, + handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id, + serf_response_handler_t handler); -apr_pool_t *test_setup(void); -void test_teardown(apr_pool_t *test_pool); +/* Mock bucket type and constructor */ +typedef struct { + int times; + const char *data; + apr_status_t status; +} mockbkt_action; + +void read_and_check_bucket(CuTest *tc, serf_bucket_t *bkt, + const char *expected); +void readlines_and_check_bucket(CuTest *tc, serf_bucket_t *bkt, + int acceptable, + const char *expected, + int expected_nr_of_lines); + +extern const serf_bucket_type_t serf_bucket_type_mock; +#define SERF_BUCKET_IS_MOCK(b) SERF_BUCKET_CHECK((b), mock) + +serf_bucket_t *serf_bucket_mock_create(mockbkt_action *actions, + int len, + serf_bucket_alloc_t *allocator); +apr_status_t serf_bucket_mock_more_data_arrived(serf_bucket_t *bucket); #endif /* TEST_SERF_H */ diff -Nru serf-1.1.0/test/test_ssl.c serf-1.3.3/test/test_ssl.c --- serf-1.1.0/test/test_ssl.c 2012-04-19 21:43:22.000000000 +0000 +++ serf-1.3.3/test/test_ssl.c 2013-05-05 20:23:31.000000000 +0000 @@ -36,7 +36,7 @@ serf_ssl_context_t *ssl_context; apr_status_t status; - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(test_pool, NULL, NULL); @@ -52,39 +52,57 @@ status = serf_ssl_use_default_certificates(ssl_context); CuAssertIntEquals(tc, APR_SUCCESS, status); - test_teardown(test_pool); } + +static const char * get_ca_file(apr_pool_t *pool, const char * file) +{ + char *srcdir = ""; + + if (apr_env_get(&srcdir, "srcdir", pool) == APR_SUCCESS) { + return apr_pstrcat(pool, srcdir, "/", file, NULL); + } + else { + return file; + } +} + + /* Test that loading a custom CA certificate file works. */ static void test_ssl_load_cert_file(CuTest *tc) { serf_ssl_certificate_t *cert = NULL; - apr_pool_t *test_pool = test_setup(); - apr_status_t status = serf_ssl_load_cert_file(&cert, "test/serftestca.pem", - test_pool); + apr_pool_t *test_pool = tc->testBaton; + apr_status_t status = serf_ssl_load_cert_file( + &cert, get_ca_file(test_pool, "test/serftestca.pem"), test_pool); CuAssertIntEquals(tc, APR_SUCCESS, status); CuAssertPtrNotNull(tc, cert); - test_teardown(test_pool); } -/* Test that reading a custom CA certificate file works. */ +/* Test that reading the subject from a custom CA certificate file works. */ static void test_ssl_cert_subject(CuTest *tc) { apr_hash_t *subject; serf_ssl_certificate_t *cert = NULL; apr_status_t status; - apr_pool_t *test_pool = test_setup(); + apr_pool_t *test_pool = tc->testBaton; - status = serf_ssl_load_cert_file(&cert, "test/serftestca.pem", test_pool); + status = serf_ssl_load_cert_file(&cert, get_ca_file(test_pool, + "test/serftestca.pem"), + test_pool); CuAssertIntEquals(tc, APR_SUCCESS, status); CuAssertPtrNotNull(tc, cert); subject = serf_ssl_cert_subject(cert, test_pool); - CuAssertStrEquals(tc, "Test Suite", + CuAssertPtrNotNull(tc, subject); + + CuAssertStrEquals(tc, "Serf", + apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "Test Suite", apr_hash_get(subject, "OU", APR_HASH_KEY_STRING)); CuAssertStrEquals(tc, "In Serf we trust, Inc.", apr_hash_get(subject, "O", APR_HASH_KEY_STRING)); @@ -96,17 +114,183 @@ apr_hash_get(subject, "C", APR_HASH_KEY_STRING)); CuAssertStrEquals(tc, "serf@example.com", apr_hash_get(subject, "E", APR_HASH_KEY_STRING)); +} + +/* Test that reading the issuer from a custom CA certificate file works. */ +static void test_ssl_cert_issuer(CuTest *tc) +{ + apr_hash_t *issuer; + serf_ssl_certificate_t *cert = NULL; + apr_status_t status; + + apr_pool_t *test_pool = tc->testBaton; - test_teardown(test_pool); + status = serf_ssl_load_cert_file(&cert, get_ca_file(test_pool, + "test/serftestca.pem"), + test_pool); + + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertPtrNotNull(tc, cert); + + issuer = serf_ssl_cert_issuer(cert, test_pool); + CuAssertPtrNotNull(tc, issuer); + + /* TODO: create a new test certificate with different issuer and subject. */ + CuAssertStrEquals(tc, "Serf", + apr_hash_get(issuer, "CN", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "Test Suite", + apr_hash_get(issuer, "OU", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "In Serf we trust, Inc.", + apr_hash_get(issuer, "O", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "Mechelen", + apr_hash_get(issuer, "L", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "Antwerp", + apr_hash_get(issuer, "ST", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "BE", + apr_hash_get(issuer, "C", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "serf@example.com", + apr_hash_get(issuer, "E", APR_HASH_KEY_STRING)); +} + +/* Test that reading the notBefore,notAfter,sha1 fingerprint and subjectAltNames + from a custom CA certificate file works. */ +static void test_ssl_cert_certificate(CuTest *tc) +{ + apr_hash_t *kv; + serf_ssl_certificate_t *cert = NULL; + apr_array_header_t *san_arr; + apr_status_t status; + + apr_pool_t *test_pool = tc->testBaton; + + status = serf_ssl_load_cert_file(&cert, get_ca_file(test_pool, + "test/serftestca.pem"), + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertPtrNotNull(tc, cert); + + kv = serf_ssl_cert_certificate(cert, test_pool); + CuAssertPtrNotNull(tc, kv); + + CuAssertStrEquals(tc, "8A:4C:19:D5:F2:52:4E:35:49:5E:7A:14:80:B2:02:BD:B4:4D:22:18", + apr_hash_get(kv, "sha1", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "Mar 21 13:18:17 2008 GMT", + apr_hash_get(kv, "notBefore", APR_HASH_KEY_STRING)); + CuAssertStrEquals(tc, "Mar 21 13:18:17 2011 GMT", + apr_hash_get(kv, "notAfter", APR_HASH_KEY_STRING)); + + /* TODO: create a new test certificate with a/some sAN's. */ + san_arr = apr_hash_get(kv, "subjectAltName", APR_HASH_KEY_STRING); + CuAssertTrue(tc, san_arr == NULL); +} + +static const char *extract_cert_from_pem(const char *pemdata, + apr_pool_t *pool) +{ + enum { INIT, CERT_BEGIN, CERT_FOUND } state; + serf_bucket_t *pembkt; + const char *begincert = "-----BEGIN CERTIFICATE-----"; + const char *endcert = "-----END CERTIFICATE-----"; + char *certdata = ""; + apr_size_t certlen = 0; + apr_status_t status = APR_SUCCESS; + + serf_bucket_alloc_t *alloc = serf_bucket_allocator_create(pool, + NULL, NULL); + + /* Extract the certificate from the .pem file, also remove newlines. */ + pembkt = SERF_BUCKET_SIMPLE_STRING(pemdata, alloc); + state = INIT; + while (state != CERT_FOUND && status != APR_EOF) { + const char *data; + apr_size_t len; + int found; + + status = serf_bucket_readline(pembkt, SERF_NEWLINE_ANY, &found, + &data, &len); + if (SERF_BUCKET_READ_ERROR(status)) + return NULL; + + if (state == INIT) { + if (strncmp(begincert, data, strlen(begincert)) == 0) + state = CERT_BEGIN; + } else if (state == CERT_BEGIN) { + if (strncmp(endcert, data, strlen(endcert)) == 0) + state = CERT_FOUND; + else { + certdata = apr_pstrcat(pool, certdata, data, NULL); + certlen += len; + switch (found) { + case SERF_NEWLINE_CR: + case SERF_NEWLINE_LF: + certdata[certlen-1] = '\0'; + certlen --; + break; + case SERF_NEWLINE_CRLF: + certdata[certlen-2] = '\0'; + certlen-=2; + break; + } + } + } + } + + if (state == CERT_FOUND) + return certdata; + else + return NULL; +} + +static void test_ssl_cert_export(CuTest *tc) +{ + serf_ssl_certificate_t *cert = NULL; + apr_file_t *fp; + apr_finfo_t file_info; + const char *base64derbuf; + char *pembuf; + apr_size_t pemlen; + apr_status_t status; + + apr_pool_t *test_pool = tc->testBaton; + + status = serf_ssl_load_cert_file(&cert, get_ca_file(test_pool, + "test/serftestca.pem"), + test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + CuAssertPtrNotNull(tc, cert); + + /* A .pem file contains a Base64 encoded DER certificate, which is exactly + what serf_ssl_cert_export is supposed to be returning. */ + status = apr_file_open(&fp, "test/serftestca.pem", + APR_FOPEN_READ | APR_FOPEN_BINARY, + APR_FPROT_OS_DEFAULT, test_pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + apr_file_info_get(&file_info, APR_FINFO_SIZE, fp); + pembuf = apr_palloc(test_pool, file_info.size); + + status = apr_file_read_full(fp, pembuf, file_info.size, &pemlen); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + base64derbuf = serf_ssl_cert_export(cert, test_pool); + + CuAssertStrEquals(tc, + extract_cert_from_pem(pembuf, test_pool), + base64derbuf); } CuSuite *test_ssl(void) { CuSuite *suite = CuSuiteNew(); + CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown); + SUITE_ADD_TEST(suite, test_ssl_init); SUITE_ADD_TEST(suite, test_ssl_load_cert_file); SUITE_ADD_TEST(suite, test_ssl_cert_subject); + SUITE_ADD_TEST(suite, test_ssl_cert_issuer); + SUITE_ADD_TEST(suite, test_ssl_cert_certificate); + SUITE_ADD_TEST(suite, test_ssl_cert_export); return suite; } diff -Nru serf-1.1.0/test/test_util.c serf-1.3.3/test/test_util.c --- serf-1.1.0/test/test_util.c 2011-07-13 03:22:01.000000000 +0000 +++ serf-1.3.3/test/test_util.c 2013-09-29 06:37:46.000000000 +0000 @@ -15,6 +15,8 @@ #include "apr.h" #include "apr_pools.h" +#include + #include #include "serf.h" @@ -27,7 +29,18 @@ /* Server setup function(s) */ -#define SERV_URL "http://localhost:" SERV_PORT_STR +#define HTTP_SERV_URL "http://localhost:" SERV_PORT_STR +#define HTTPS_SERV_URL "https://localhost:" SERV_PORT_STR + +/* cleanup for conn */ +static apr_status_t cleanup_conn(void *baton) +{ + serf_connection_t *conn = baton; + + serf_connection_close(conn); + + return APR_SUCCESS; +} static apr_status_t default_server_address(apr_sockaddr_t **address, apr_pool_t *pool) @@ -57,27 +70,86 @@ } /* Default implementation of a serf_connection_setup_t callback. */ -static apr_status_t default_conn_setup(apr_socket_t *skt, - serf_bucket_t **input_bkt, - serf_bucket_t **output_bkt, - void *setup_baton, - apr_pool_t *pool) +static apr_status_t default_http_conn_setup(apr_socket_t *skt, + serf_bucket_t **input_bkt, + serf_bucket_t **output_bkt, + void *setup_baton, + apr_pool_t *pool) +{ + test_baton_t *tb = setup_baton; + + *input_bkt = serf_bucket_socket_create(skt, tb->bkt_alloc); + return APR_SUCCESS; +} + +/* This function makes serf use SSL on the connection. */ +apr_status_t default_https_conn_setup(apr_socket_t *skt, + serf_bucket_t **input_bkt, + serf_bucket_t **output_bkt, + void *setup_baton, + apr_pool_t *pool) { - test_baton_t *ctx = setup_baton; + test_baton_t *tb = setup_baton; + + *input_bkt = serf_bucket_socket_create(skt, tb->bkt_alloc); + *input_bkt = serf_bucket_ssl_decrypt_create(*input_bkt, NULL, + tb->bkt_alloc); + tb->ssl_context = serf_bucket_ssl_encrypt_context_get(*input_bkt); + + if (output_bkt) { + *output_bkt = serf_bucket_ssl_encrypt_create(*output_bkt, + tb->ssl_context, + tb->bkt_alloc); + } + + if (tb->server_cert_cb) + serf_ssl_server_cert_callback_set(tb->ssl_context, + tb->server_cert_cb, + tb); + + serf_ssl_set_hostname(tb->ssl_context, "localhost"); - *input_bkt = serf_bucket_socket_create(skt, ctx->bkt_alloc); return APR_SUCCESS; } +apr_status_t use_new_connection(test_baton_t *tb, + apr_pool_t *pool) +{ + apr_uri_t url; + apr_status_t status; + + if (tb->connection) + cleanup_conn(tb->connection); + tb->connection = NULL; + + status = apr_uri_parse(pool, tb->serv_url, &url); + if (status != APR_SUCCESS) + return status; + + status = serf_connection_create2(&tb->connection, tb->context, + url, + tb->conn_setup, + tb, + default_closed_connection, + tb, + pool); + apr_pool_cleanup_register(pool, tb->connection, cleanup_conn, + apr_pool_cleanup_null); + + return status; +} +/* Setup the client context, ready to connect and send requests to a + server.*/ static apr_status_t setup(test_baton_t **tb_p, serf_connection_setup_t conn_setup, + const char *serv_url, int use_proxy, + apr_size_t message_count, apr_pool_t *pool) { - apr_status_t status; test_baton_t *tb; - apr_uri_t url; + apr_status_t status; tb = apr_pcalloc(pool, sizeof(*tb)); *tb_p = tb; @@ -86,6 +158,13 @@ tb->context = serf_context_create(pool); tb->bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL); + tb->accepted_requests = apr_array_make(pool, message_count, sizeof(int)); + tb->sent_requests = apr_array_make(pool, message_count, sizeof(int)); + tb->handled_requests = apr_array_make(pool, message_count, sizeof(int)); + + tb->serv_url = serv_url; + tb->conn_setup = conn_setup; + status = default_server_address(&tb->serv_addr, pool); if (status != APR_SUCCESS) return status; @@ -99,39 +178,69 @@ serf_config_proxy(tb->context, tb->proxy_addr); } - status = apr_uri_parse(pool, SERV_URL, &url); + status = use_new_connection(tb, pool); + + return status; +} + +/* Setup an https server and the client context to connect to that server */ +apr_status_t test_https_server_setup(test_baton_t **tb_p, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + serf_connection_setup_t conn_setup, + const char *keyfile, + const char **certfiles, + const char *client_cn, + serf_ssl_need_server_cert_t server_cert_cb, + apr_pool_t *pool) +{ + apr_status_t status; + test_baton_t *tb; + + status = setup(tb_p, + conn_setup ? conn_setup : default_https_conn_setup, + HTTPS_SERV_URL, + FALSE, + message_count, + pool); if (status != APR_SUCCESS) return status; - status = serf_connection_create2(&tb->connection, tb->context, - url, - conn_setup ? conn_setup : - default_conn_setup, - tb, - default_closed_connection, - tb, - pool); + tb = *tb_p; + tb->server_cert_cb = server_cert_cb; + + /* Prepare a server. */ + setup_https_test_server(&tb->serv_ctx, tb->serv_addr, + message_list, message_count, + action_list, action_count, options, + keyfile, certfiles, client_cn, + pool); + status = start_test_server(tb->serv_ctx); return status; } - - -apr_status_t test_server_setup(test_baton_t **tb_p, - test_server_message_t *message_list, - apr_size_t message_count, - test_server_action_t *action_list, - apr_size_t action_count, - apr_int32_t options, - serf_connection_setup_t conn_setup, - apr_pool_t *pool) +/* Setup an http server and the client context to connect to that server */ +apr_status_t test_http_server_setup(test_baton_t **tb_p, + test_server_message_t *message_list, + apr_size_t message_count, + test_server_action_t *action_list, + apr_size_t action_count, + apr_int32_t options, + serf_connection_setup_t conn_setup, + apr_pool_t *pool) { apr_status_t status; test_baton_t *tb; status = setup(tb_p, - conn_setup, + conn_setup ? conn_setup : default_http_conn_setup, + HTTP_SERV_URL, FALSE, + message_count, pool); if (status != APR_SUCCESS) return status; @@ -139,13 +248,17 @@ tb = *tb_p; /* Prepare a server. */ - status = test_start_server(&tb->serv_ctx, tb->serv_addr, - message_list, message_count, - action_list, action_count, options, pool); + setup_test_server(&tb->serv_ctx, tb->serv_addr, + message_list, message_count, + action_list, action_count, options, + pool); + status = start_test_server(tb->serv_ctx); return status; } +/* Setup a proxy server and an http server and the client context to connect to + that proxy server */ apr_status_t test_server_proxy_setup(test_baton_t **tb_p, test_server_message_t *serv_message_list, @@ -164,8 +277,10 @@ test_baton_t *tb; status = setup(tb_p, - conn_setup, + conn_setup ? conn_setup : default_http_conn_setup, + HTTP_SERV_URL, TRUE, + serv_message_count, pool); if (status != APR_SUCCESS) return status; @@ -173,42 +288,325 @@ tb = *tb_p; /* Prepare the server. */ - status = test_start_server(&tb->serv_ctx, tb->serv_addr, - serv_message_list, serv_message_count, - serv_action_list, serv_action_count, - options, pool); + setup_test_server(&tb->serv_ctx, tb->serv_addr, + serv_message_list, serv_message_count, + serv_action_list, serv_action_count, + options, + pool); + status = start_test_server(tb->serv_ctx); if (status != APR_SUCCESS) return status; /* Prepare the proxy. */ - status = test_start_server(&tb->proxy_ctx, tb->proxy_addr, - proxy_message_list, proxy_message_count, - proxy_action_list, proxy_action_count, - options, pool); + setup_test_server(&tb->proxy_ctx, tb->proxy_addr, + proxy_message_list, proxy_message_count, + proxy_action_list, proxy_action_count, + options, + pool); + status = start_test_server(tb->proxy_ctx); return status; } -apr_status_t test_server_teardown(test_baton_t *tb, apr_pool_t *pool) +/* Setup a proxy server and a https server and the client context to connect to + that proxy server */ +apr_status_t +test_https_server_proxy_setup(test_baton_t **tb_p, + test_server_message_t *serv_message_list, + apr_size_t serv_message_count, + test_server_action_t *serv_action_list, + apr_size_t serv_action_count, + test_server_message_t *proxy_message_list, + apr_size_t proxy_message_count, + test_server_action_t *proxy_action_list, + apr_size_t proxy_action_count, + apr_int32_t options, + serf_connection_setup_t conn_setup, + const char *keyfile, + const char **certfiles, + const char *client_cn, + serf_ssl_need_server_cert_t server_cert_cb, + apr_pool_t *pool) { - serf_connection_close(tb->connection); + apr_status_t status; + test_baton_t *tb; - if (tb->serv_ctx) - test_server_destroy(tb->serv_ctx, pool); - if (tb->proxy_ctx) - test_server_destroy(tb->proxy_ctx, pool); + status = setup(tb_p, + conn_setup ? conn_setup : default_https_conn_setup, + HTTPS_SERV_URL, + TRUE, /* use proxy */ + serv_message_count, + pool); + if (status != APR_SUCCESS) + return status; - return APR_SUCCESS; + tb = *tb_p; + tb->server_cert_cb = server_cert_cb; + + /* Prepare a https server. */ + setup_https_test_server(&tb->serv_ctx, tb->serv_addr, + serv_message_list, serv_message_count, + serv_action_list, serv_action_count, + options, + keyfile, certfiles, client_cn, + pool); + status = start_test_server(tb->serv_ctx); + + /* Prepare the proxy. */ + setup_test_server(&tb->proxy_ctx, tb->proxy_addr, + proxy_message_list, proxy_message_count, + proxy_action_list, proxy_action_count, + options, + pool); + status = start_test_server(tb->proxy_ctx); + + return status; } -apr_pool_t *test_setup(void) +void *test_setup(void *dummy) { apr_pool_t *test_pool; apr_pool_create(&test_pool, NULL); return test_pool; } -void test_teardown(apr_pool_t *test_pool) +void *test_teardown(void *baton) +{ + apr_pool_t *pool = baton; + apr_pool_destroy(pool); + + return NULL; +} + +/* Helper function, runs the client and server context loops and validates + that no errors were encountered, and all messages were sent and received. */ +apr_status_t +test_helper_run_requests_no_check(CuTest *tc, test_baton_t *tb, + int num_requests, + handler_baton_t handler_ctx[], + apr_pool_t *pool) +{ + apr_pool_t *iter_pool; + int i, done = 0; + apr_status_t status; + + apr_pool_create(&iter_pool, pool); + + while (!done) + { + apr_pool_clear(iter_pool); + + /* run server event loop */ + status = run_test_server(tb->serv_ctx, 0, iter_pool); + if (!APR_STATUS_IS_TIMEUP(status) && + SERF_BUCKET_READ_ERROR(status)) + return status; + + /* run proxy event loop */ + if (tb->proxy_ctx) { + status = run_test_server(tb->proxy_ctx, 0, iter_pool); + if (!APR_STATUS_IS_TIMEUP(status) && + SERF_BUCKET_READ_ERROR(status)) + return status; + } + + /* run client event loop */ + status = serf_context_run(tb->context, 0, iter_pool); + if (!APR_STATUS_IS_TIMEUP(status) && + SERF_BUCKET_READ_ERROR(status)) + return status; + + done = 1; + for (i = 0; i < num_requests; i++) + done &= handler_ctx[i].done; + } + apr_pool_destroy(iter_pool); + + return APR_SUCCESS; +} + +void +test_helper_run_requests_expect_ok(CuTest *tc, test_baton_t *tb, + int num_requests, + handler_baton_t handler_ctx[], + apr_pool_t *pool) +{ + apr_status_t status; + + status = test_helper_run_requests_no_check(tc, tb, num_requests, + handler_ctx, pool); + CuAssertIntEquals(tc, APR_SUCCESS, status); + + /* Check that all requests were received */ + CuAssertIntEquals(tc, num_requests, tb->sent_requests->nelts); + CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts); + CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts); +} + +serf_bucket_t* accept_response(serf_request_t *request, + serf_bucket_t *stream, + void *acceptor_baton, + apr_pool_t *pool) +{ + serf_bucket_t *c; + serf_bucket_alloc_t *bkt_alloc; + handler_baton_t *ctx = acceptor_baton; + serf_bucket_t *response; + + /* get the per-request bucket allocator */ + bkt_alloc = serf_request_get_alloc(request); + + /* Create a barrier so the response doesn't eat us! */ + c = serf_bucket_barrier_create(stream, bkt_alloc); + + APR_ARRAY_PUSH(ctx->accepted_requests, int) = ctx->req_id; + + response = serf_bucket_response_create(c, bkt_alloc); + + if (strcasecmp(ctx->method, "HEAD") == 0) + serf_bucket_response_set_head(response); + + return response; +} + +apr_status_t setup_request(serf_request_t *request, + void *setup_baton, + serf_bucket_t **req_bkt, + serf_response_acceptor_t *acceptor, + void **acceptor_baton, + serf_response_handler_t *handler, + void **handler_baton, + apr_pool_t *pool) +{ + handler_baton_t *ctx = setup_baton; + serf_bucket_t *body_bkt; + + if (ctx->request) + { + /* Create a raw request bucket. */ + *req_bkt = serf_bucket_simple_create(ctx->request, strlen(ctx->request), + NULL, NULL, + serf_request_get_alloc(request)); + } + else + { + if (ctx->req_id >= 0) { + /* create a simple body text */ + const char *str = apr_psprintf(pool, "%d", ctx->req_id); + + body_bkt = serf_bucket_simple_create( + str, strlen(str), NULL, NULL, + serf_request_get_alloc(request)); + } + else + body_bkt = NULL; + + *req_bkt = + serf_request_bucket_request_create(request, + ctx->method, ctx->path, + body_bkt, + serf_request_get_alloc(request)); + } + + APR_ARRAY_PUSH(ctx->sent_requests, int) = ctx->req_id; + + *acceptor = ctx->acceptor; + *acceptor_baton = ctx; + *handler = ctx->handler; + *handler_baton = ctx; + + return APR_SUCCESS; +} + +apr_status_t handle_response(serf_request_t *request, + serf_bucket_t *response, + void *handler_baton, + apr_pool_t *pool) +{ + handler_baton_t *ctx = handler_baton; + + if (! response) { + serf_connection_request_create(ctx->tb->connection, + setup_request, + ctx); + return APR_SUCCESS; + } + + while (1) { + apr_status_t status; + const char *data; + apr_size_t len; + + status = serf_bucket_read(response, 2048, &data, &len); + if (SERF_BUCKET_READ_ERROR(status)) + return status; + + if (APR_STATUS_IS_EOF(status)) { + APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id; + ctx->done = TRUE; + return APR_EOF; + } + + if (APR_STATUS_IS_EAGAIN(status)) { + return status; + } + + } + + return APR_SUCCESS; +} + +void setup_handler(test_baton_t *tb, handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id, + serf_response_handler_t handler) +{ + handler_ctx->method = method; + handler_ctx->path = path; + handler_ctx->done = FALSE; + + handler_ctx->acceptor = accept_response; + handler_ctx->acceptor_baton = NULL; + handler_ctx->handler = handler ? handler : handle_response; + handler_ctx->req_id = req_id; + handler_ctx->accepted_requests = tb->accepted_requests; + handler_ctx->sent_requests = tb->sent_requests; + handler_ctx->handled_requests = tb->handled_requests; + handler_ctx->tb = tb; + handler_ctx->request = NULL; +} + +void create_new_prio_request(test_baton_t *tb, + handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id) +{ + setup_handler(tb, handler_ctx, method, path, req_id, NULL); + serf_connection_priority_request_create(tb->connection, + setup_request, + handler_ctx); +} + +void create_new_request(test_baton_t *tb, + handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id) +{ + setup_handler(tb, handler_ctx, method, path, req_id, NULL); + serf_connection_request_create(tb->connection, + setup_request, + handler_ctx); +} + +void +create_new_request_with_resp_hdlr(test_baton_t *tb, + handler_baton_t *handler_ctx, + const char *method, const char *path, + int req_id, + serf_response_handler_t handler) { - apr_pool_destroy(test_pool); + setup_handler(tb, handler_ctx, method, path, req_id, handler); + serf_connection_request_create(tb->connection, + setup_request, + handler_ctx); }