Hello community, here is the log from the commit of package libserf for openSUSE:Factory checked in at 2013-10-06 14:27:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libserf (Old) and /work/SRC/openSUSE:Factory/.libserf.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libserf" Changes: -------- --- /work/SRC/openSUSE:Factory/libserf/libserf.changes 2013-09-29 17:49:08.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.libserf.new/libserf.changes 2013-10-06 14:27:53.000000000 +0200 @@ -1,0 +2,21 @@ +Fri Oct 4 20:45:19 UTC 2013 - andreas.stie...@gmx.de + +- update to 1.3.2 +- bugs fixed: + * HTTP headers should be treated case-insensitively + * Compilation breaks with Codewarrior compiler + * Fix crash during cleanup of SSL buckets in apr_terminate() + * Fix host header when url contains a username or password + * Handle authentication for responses to HEAD requests + * Improve serf_get: add option to add request headers, allow url + with query, allow HEAD requests + * Improve RFC conformance: don't expect body for certain responses + * Do not invoke progress callback when no data was received + * And more test suite fixes and build warning cleanups +- SCons-related fixes: + * Fix build when GSSAPI not in default include path + - Use both MAJOR and MINOR version for the shared library name + Fix the .pc file when installing serf in a non-default LIBDIR +- drop serf-1.3.x-shlibver-soname.patch, committed upstream + +------------------------------------------------------------------- Old: ---- serf-1.3.1.tar.bz2 serf-1.3.x-shlibver-soname.patch New: ---- serf-1.3.2.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libserf.spec ++++++ --- /var/tmp/diff_new_pack.yf4wyj/_old 2013-10-06 14:27:54.000000000 +0200 +++ /var/tmp/diff_new_pack.yf4wyj/_new 2013-10-06 14:27:54.000000000 +0200 @@ -24,13 +24,12 @@ %define major 1 %define minor 3 %define SHLIBVER %major.%minor.0 -Version: 1.3.1 +Version: 1.3.2 Release: 0 Summary: High-Performance Asynchronous HTTP Client Library License: Apache-2.0 Group: System/Libraries Source: https://serf.googlecode.com/files/serf-%{version}.tar.bz2 -Patch1: serf-1.3.x-shlibver-soname.patch Url: https://serf.googlecode.com BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: gcc @@ -112,7 +111,6 @@ %prep %setup -q -n "serf-%{version}" -%patch1 -p1 %build scons \ ++++++ serf-1.3.1.tar.bz2 -> serf-1.3.2.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/CHANGES new/serf-1.3.2/CHANGES --- old/serf-1.3.1/CHANGES 2013-08-15 21:16:24.000000000 +0200 +++ new/serf-1.3.2/CHANGES 2013-10-04 20:33:48.000000000 +0200 @@ -1,4 +1,26 @@ -Serf 1.3.1 [2013-08-15, from /tags/1.3.1, r????] +Serf 1.3.2 [2013-10-04, from /tags/1.3.2, r????] + 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 @@ -17,6 +39,7 @@ 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/SConstruct new/serf-1.3.2/SConstruct --- old/serf-1.3.1/SConstruct 2013-08-15 11:13:20.000000000 +0200 +++ new/serf-1.3.2/SConstruct 2013-10-04 17:11:04.000000000 +0200 @@ -204,9 +204,15 @@ libdir = '$LIBDIR' incdir = '$PREFIX/include/serf-$MAJOR' -env['SHLIBVERSION']='${MINOR}.0.0' +# 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-${MAJOR}' +LIBNAME = 'libserf-%d' % (MAJOR,) if sys.platform != 'win32': LIBNAMESTATIC = LIBNAME else: @@ -218,10 +224,6 @@ 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,)) - # 'man ld' says positive non-zero for the first number, so we add one. - # Mac's interpretation of compatibility is the same as our MINOR version. - env.Append(LINKFLAGS='-Wl,-compatibility_version,%d' % (MINOR+1,)) - env.Append(LINKFLAGS='-Wl,-current_version,%d.%d' % (MINOR+1, PATCH,)) if sys.platform != 'win32': ### gcc only. figure out appropriate test / better way to check these @@ -259,6 +261,7 @@ # Optimize for speed, use DLL runtime env.Append(CCFLAGS=['/O2', '/MD']) env.Append(CPPDEFINES='NDEBUG') + env.Append(LINKFLAGS='/RELEASE') # PLAN THE BUILD SHARED_SOURCES = [] @@ -354,6 +357,7 @@ # 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) @@ -362,12 +366,11 @@ if sys.platform == 'win32': env.Append(CPPDEFINES=['SERF_HAVE_SSPI']) -# On Solaris, the -R values that APR describes never make it into actual +# 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. -if sys.platform == 'sunos5': - for d in env['LIBPATH']: - env.Append(RPATH=':'+d) +for d in env['LIBPATH']: + env.Append(RPATH=':'+d) # Set up the construction of serf-*.pc pkgconfig = env.Textfile('serf-%d.pc' % (MAJOR,), @@ -375,6 +378,7 @@ 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, @@ -397,17 +401,19 @@ 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=<path> is specified, install_shared_path will point - # to a path in the sandbox. The shared library install name (id) should be the - # final targat path. + # 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, lib_shared[0].name) + 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))) - ### construct shared lib symlinks. this also means install the lib - ### as libserf-2.1.0.0.dylib, then add the symlinks. - ### note: see InstallAs env.Alias('install-lib', [install_static, install_shared, ]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/auth/auth.c new/serf-1.3.2/auth/auth.c --- old/serf-1.3.1/auth/auth.c 2013-08-15 11:00:57.000000000 +0200 +++ new/serf-1.3.2/auth/auth.c 2013-09-29 08:37:46.000000000 +0200 @@ -234,7 +234,7 @@ char *auth_name, *c; /* We're only interested in xxxx-Authenticate headers. */ - if (strcmp(key, ab->header) != 0) + if (strcasecmp(key, ab->header) != 0) return 0; /* Extract the authentication scheme name. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/auth/auth_basic.c new/serf-1.3.2/auth/auth_basic.c --- old/serf-1.3.1/auth/auth_basic.c 2013-07-04 21:58:40.000000000 +0200 +++ new/serf-1.3.2/auth/auth_basic.c 2013-08-17 23:58:47.000000000 +0200 @@ -48,7 +48,7 @@ apr_status_t status; apr_pool_t *cred_pool; char *username, *password, *realm_name; - const char *eq, *realm; + const char *eq, *realm = NULL; /* Can't do Basic authentication if there's no callback to get username & password. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/auth/auth_digest.c new/serf-1.3.2/auth/auth_digest.c --- old/serf-1.3.1/auth/auth_digest.c 2013-08-15 11:00:57.000000000 +0200 +++ new/serf-1.3.2/auth/auth_digest.c 2013-10-03 20:17:40.000000000 +0200 @@ -96,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) @@ -113,12 +114,17 @@ realm_name, password); status = apr_md5(ha1, tmp, strlen(tmp)); + if (status) + return status; + + *out_ha1 = hex_encode(ha1, pool); - return 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) @@ -134,17 +140,21 @@ method, uri); status = apr_md5(ha2, tmp, strlen(tmp)); + if (status) + return status; - return hex_encode(ha2, pool); + *out_ha2 = 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) @@ -156,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\"," @@ -194,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); @@ -207,7 +222,9 @@ digest_info->algorithm); } - return hdr; + *out_header = hdr; + + return APR_SUCCESS; } apr_status_t @@ -330,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); @@ -339,7 +356,7 @@ likes. */ serf_connection_set_max_outstanding_requests(conn, 0); - return APR_SUCCESS; + return status; } apr_status_t @@ -387,7 +404,7 @@ serf_context_t *ctx = conn->ctx; serf__authn_info_t *authn_info; digest_authn_info_t *digest_info; - apr_status_t status = APR_SUCCESS; + apr_status_t status; if (peer == HOST) { authn_info = serf__get_authn_info_for_server(conn); @@ -421,8 +438,10 @@ /* Build a new Authorization header. */ digest_info->header = (peer == HOST) ? "Authorization" : "Proxy-Authorization"; - value = build_auth_header(digest_info, 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); @@ -431,10 +450,10 @@ /* 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 = path; + request->auth_baton = (void *)path; } - return status; + return APR_SUCCESS; } apr_status_t @@ -454,6 +473,7 @@ const char *nc_str = NULL; serf_bucket_t *hdrs; serf_context_t *ctx = conn->ctx; + apr_status_t status; hdrs = serf_bucket_response_get_headers(response); @@ -517,7 +537,10 @@ } digest_info = authn_info->baton; - ha2 = build_digest_ha2(req_uri, "", qop, pool); + status = build_digest_ha2(&ha2, req_uri, "", qop, pool); + if (status) + return status; + 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/buckets/response_buckets.c new/serf-1.3.2/buckets/response_buckets.c --- old/serf-1.3.1/buckets/response_buckets.c 2013-05-20 13:25:39.000000000 +0200 +++ new/serf-1.3.2/buckets/response_buckets.c 2013-09-29 08:37:46.000000000 +0200 @@ -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); @@ -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: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/buckets/socket_buckets.c new/serf-1.3.2/buckets/socket_buckets.c --- old/serf-1.3.1/buckets/socket_buckets.c 2012-10-07 11:19:35.000000000 +0200 +++ new/serf-1.3.2/buckets/socket_buckets.c 2013-09-29 08:37:46.000000000 +0200 @@ -50,7 +50,7 @@ "--- socket_recv:\n%.*s\n-(%d)-\n", *len, buf, *len); - if (ctx->progress_func) + if (ctx->progress_func && *len) ctx->progress_func(ctx->progress_baton, *len, 0); return status; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/buckets/ssl_buckets.c new/serf-1.3.2/buckets/ssl_buckets.c --- old/serf-1.3.1/buckets/ssl_buckets.c 2013-07-21 16:21:27.000000000 +0200 +++ new/serf-1.3.2/buckets/ssl_buckets.c 2013-09-29 08:37:46.000000000 +0200 @@ -1198,21 +1198,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()); @@ -1269,8 +1264,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); @@ -1283,10 +1276,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; } @@ -1300,7 +1290,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; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/build/gen_def.py new/serf-1.3.2/build/gen_def.py --- old/serf-1.3.1/build/gen_def.py 2013-07-21 16:24:52.000000000 +0200 +++ new/serf-1.3.2/build/gen_def.py 2013-09-04 22:19:57.000000000 +0200 @@ -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: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/build/serf.pc.in new/serf-1.3.2/build/serf.pc.in --- old/serf-1.3.1/build/serf.pc.in 2011-08-06 09:52:19.000000000 +0200 +++ new/serf-1.3.2/build/serf.pc.in 2013-10-04 17:11:04.000000000 +0200 @@ -1,7 +1,7 @@ SERF_MAJOR_VERSION=@MAJOR@ prefix=@PREFIX@ exec_prefix=${prefix} -libdir=${exec_prefix}/lib +libdir=@LIBDIR@ includedir=${prefix}/include/@INCLUDE_SUBDIR@ Name: serf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/outgoing.c new/serf-1.3.2/outgoing.c --- old/serf-1.3.1/outgoing.c 2013-08-15 11:00:57.000000000 +0200 +++ new/serf-1.3.2/outgoing.c 2013-09-29 08:37:46.000000000 +0200 @@ -428,8 +428,7 @@ 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; @@ -759,7 +758,7 @@ if (APR_STATUS_IS_EPIPE(status) || APR_STATUS_IS_ECONNRESET(status) || APR_STATUS_IS_ECONNABORTED(status)) - return no_more_writes(conn, request); + return no_more_writes(conn); if (status) return status; } @@ -849,10 +848,10 @@ if (APR_STATUS_IS_EAGAIN(status)) return APR_SUCCESS; if (APR_STATUS_IS_EPIPE(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, request); + return no_more_writes(conn); } if (status) return status; @@ -1381,7 +1380,8 @@ /* We're not interested in the path following the hostname. */ c->host_url = apr_uri_unparse(c->pool, &host_info, - APR_URI_UNP_OMITPATHINFO); + 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)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/serf.h new/serf-1.3.2/serf.h --- old/serf-1.3.1/serf.h 2013-08-05 11:59:59.000000000 +0200 +++ new/serf-1.3.2/serf.h 2013-08-15 22:07:26.000000000 +0200 @@ -1062,7 +1062,7 @@ /* Version info */ #define SERF_MAJOR_VERSION 1 #define SERF_MINOR_VERSION 3 -#define SERF_PATCH_VERSION 1 +#define SERF_PATCH_VERSION 2 /* Version number string */ #define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/serf_private.h new/serf-1.3.2/serf_private.h --- old/serf-1.3.1/serf_private.h 2013-08-15 11:00:57.000000000 +0200 +++ new/serf-1.3.2/serf_private.h 2013-09-29 08:37:46.000000000 +0200 @@ -23,7 +23,9 @@ /* 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. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/test/CuTest.c new/serf-1.3.2/test/CuTest.c --- old/serf-1.3.1/test/CuTest.c 2013-06-26 13:23:26.000000000 +0200 +++ new/serf-1.3.2/test/CuTest.c 2013-10-04 15:14:19.000000000 +0200 @@ -215,7 +215,8 @@ const char* actual) { CuString string; - if ((expected == NULL && actual == NULL) || + if ((explen == 0) || + (expected == NULL && actual == NULL) || (expected != NULL && actual != NULL && strncmp(expected, actual, explen) == 0)) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/test/serf_get.c new/serf-1.3.2/test/serf_get.c --- old/serf-1.3.1/test/serf_get.c 2013-06-26 13:47:21.000000000 +0200 +++ new/serf-1.3.2/test/serf_get.c 2013-09-29 08:22:07.000000000 +0200 @@ -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(); } @@ -170,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); @@ -178,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 { @@ -202,6 +217,7 @@ const char *username; const char *password; int auth_attempts; + serf_bucket_t *req_hdrs; } handler_baton_t; /* Kludges for APR 0.9 support. */ @@ -211,6 +227,75 @@ #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, @@ -221,9 +306,14 @@ 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; @@ -278,57 +368,6 @@ /* 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) -{ - 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"); - - *acceptor = ctx->acceptor; - *acceptor_baton = ctx->acceptor_baton; - *handler = ctx->handler; - *handler_baton = ctx; - - return APR_SUCCESS; -} - static apr_status_t credentials_callback(char **username, char **password, @@ -345,8 +384,8 @@ } else { - *username = ctx->username; - *password = ctx->password; + *username = (char*)ctx->username; + *password = (char*)ctx->password; ctx->auth_attempts++; return APR_SUCCESS; @@ -366,25 +405,28 @@ puts("-m <method> Use the <method> HTTP Method"); puts("-f <file> Use the <file> as the request body"); puts("-p <hostname:port> Use the <host:port> as proxy server"); + puts("-r <header:value> Use <header:value> 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, inflight; int i; int print_headers; - char *username = NULL; - char *password = ""; + const char *username = NULL; + const char *password = ""; apr_getopt_t *opt; char opt_c; const char *opt_arg; @@ -394,6 +436,7 @@ apr_pool_create(&pool, NULL); /* serf_initialize(); */ + bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL); /* Default to one round of fetching with no limit to max inflight reqs. */ count = 1; @@ -405,7 +448,7 @@ apr_getopt_init(&opt, pool, argc, argv); - while ((status = apr_getopt(opt, "U:P:f:hHm:n:vp:x:", &opt_c, &opt_arg)) == + while ((status = apr_getopt(opt, "U:P:f:hHm:n:vp:x:r:", &opt_c, &opt_arg)) == APR_SUCCESS) { switch (opt_c) { @@ -449,6 +492,28 @@ 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); @@ -479,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); @@ -537,7 +609,7 @@ 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, @@ -556,7 +628,11 @@ handler_ctx.host = url.hostinfo; handler_ctx.method = method; - handler_ctx.path = url.path; + 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; @@ -566,6 +642,7 @@ 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); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/test/test_auth.c new/serf-1.3.2/test/test_auth.c --- old/serf-1.3.1/test/test_auth.c 2013-07-04 21:58:40.000000000 +0200 +++ new/serf-1.3.2/test/test_auth.c 2013-09-29 08:37:46.000000000 +0200 @@ -182,11 +182,12 @@ "0" CRLF CRLF); action_list[0].kind = SERVER_RESPOND; - /* Non-standard case usage for scheme name */ + /* 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 + "www-Authenticate: bAsIc realm=""Test Suite""" CRLF "%s" CRLF "1" CRLF CRLF @@ -544,6 +545,69 @@ "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) { @@ -559,6 +623,7 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/test/test_buckets.c new/serf-1.3.2/test/test_buckets.c --- old/serf-1.3.1/test/test_buckets.c 2013-07-15 11:20:46.000000000 +0200 +++ new/serf-1.3.2/test/test_buckets.c 2013-09-29 08:37:46.000000000 +0200 @@ -1154,6 +1154,70 @@ 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(); @@ -1178,6 +1242,7 @@ 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/test/test_context.c new/serf-1.3.2/test/test_context.c --- old/serf-1.3.1/test/test_context.c 2013-08-15 11:00:57.000000000 +0200 +++ new/serf-1.3.2/test/test_context.c 2013-09-29 08:37:46.000000000 +0200 @@ -638,6 +638,47 @@ 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); + } + + test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx, + test_pool); +} /***************************************************************************** * Issue #91: test that serf correctly handle an incoming 4xx reponse while @@ -2161,12 +2202,14 @@ /* 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\"," + "proXy-Authenticate: Digest realm=\"Test Suite Proxy\"," "nonce=\"ABCDEF1234567890\",opaque=\"myopaque\"," "algorithm=\"MD5\",qop-options=\"auth\"" CRLF CRLF @@ -2225,6 +2268,7 @@ 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); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/serf-1.3.1/test/test_util.c new/serf-1.3.2/test/test_util.c --- old/serf-1.3.1/test/test_util.c 2013-06-22 14:15:27.000000000 +0200 +++ new/serf-1.3.2/test/test_util.c 2013-09-29 08:37:46.000000000 +0200 @@ -451,6 +451,7 @@ 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); @@ -460,7 +461,12 @@ APR_ARRAY_PUSH(ctx->accepted_requests, int) = ctx->req_id; - return serf_bucket_response_create(c, bkt_alloc); + 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, @@ -484,11 +490,17 @@ } else { - /* create a simple body text */ - const char *str = apr_psprintf(pool, "%d", ctx->req_id); + 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; - 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, -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org