diff options
79 files changed, 5044 insertions, 2431 deletions
diff --git a/Source/CTest/Curl/CMakeLists.txt b/Source/CTest/Curl/CMakeLists.txt index 898d64f..515b411 100644 --- a/Source/CTest/Curl/CMakeLists.txt +++ b/Source/CTest/Curl/CMakeLists.txt @@ -2,7 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 1.5) PROJECT(LIBCURL C) SET(PACKAGE "curl") -SET(VERSION "7.9.5") +SET(VERSION "7.10.2") +SET(PACKAGE_TARNAME " ") SET(OPERATING_SYSTEM ${CMAKE_SYSTEM_NAME}) SET(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") @@ -52,6 +53,7 @@ SET(libCurl_SRCS llist.c hash.c multi.c + content_encoding.c ) IF(WIN32) @@ -86,6 +88,11 @@ IF(HAVE_LIBWS2_32) SET(CURL_LIBS ${CURL_LIBS} ws2_32) ENDIF(HAVE_LIBWS2_32) +CHECK_LIBRARY_EXISTS("z;${CURL_LIBS}" inflateEnd "" HAVE_LIBZ) +IF(HAVE_LIBZ) + SET(CURL_LIBS ${CURL_LIBS} z) +ENDIF(HAVE_LIBZ) + SET(CMAKE_REQUIRED_LIBRARIES ${CURL_LIBS}) CHECK_INCLUDE_FILE("sys/types.h" HAVE_SYS_TYPES_H) @@ -97,6 +104,8 @@ CHECK_INCLUDE_FILE("fcntl.h" HAVE_FCNTL_H) CHECK_INCLUDE_FILE("malloc.h" HAVE_MALLOC_H) CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H) CHECK_INCLUDE_FILE("netdb.h" HAVE_NETDB_H) +CHECK_INCLUDE_FILE("zlib.h" HAVE_ZLIB_H) +CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H) CHECK_INCLUDE_FILE("netinet/in.h" HAVE_NETINET_IN_H) CHECK_INCLUDE_FILE("sys/socket.h" HAVE_SYS_SOCKET_H) @@ -140,6 +149,7 @@ CHECK_INCLUDE_FILE("winsock.h" HAVE_WINSOCK_H) CHECK_INCLUDE_FILE("sockio.h" HAVE_SOCKIO_H) CHECK_INCLUDE_FILE("sys/sockio.h" HAVE_SYS_SOCKIO_H) CHECK_INCLUDE_FILE("x509.h" HAVE_X509_H) +CHECK_INCLUDE_FILE("setjmp.h" HAVE_SETJMP_H) CHECK_TYPE_SIZE(ssize_t SIZEOF_SSIZE_T) CHECK_TYPE_SIZE("long double" SIZEOF_LONG_DOUBLE) @@ -153,6 +163,7 @@ CHECK_FUNCTION_EXISTS(_doprnt HAVE_DOPRNT) CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF) CHECK_FUNCTION_EXISTS(socket HAVE_SOCKET) +CHECK_FUNCTION_EXISTS(poll HAVE_POLL) CHECK_FUNCTION_EXISTS(select HAVE_SELECT) CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP) CHECK_FUNCTION_EXISTS(strstr HAVE_STRSTR) @@ -175,6 +186,12 @@ CHECK_FUNCTION_EXISTS(closesocket HAVE_CLOSESOCKET) CHECK_FUNCTION_EXISTS(setvbuf HAVE_SETVBUF) CHECK_FUNCTION_EXISTS(sigaction HAVE_SIGACTION) CHECK_FUNCTION_EXISTS(signal HAVE_SIGNAL) +CHECK_FUNCTION_EXISTS(sigsetjmp HAVE_SIGSETJMP) +CHECK_FUNCTION_EXISTS(__sigsetjmp HAVE___SIGSETJMP) +IF(HAVE___SIGSETJMP) + SET(HAVE_SIGSETJMP 1) +ENDIF(HAVE___SIGSETJMP) + CHECK_FUNCTION_EXISTS(getpass_r HAVE_GETPASS_R) CHECK_FUNCTION_EXISTS(strlcat HAVE_STRLCAT) CHECK_FUNCTION_EXISTS(getpwuid HAVE_GETPWUID) diff --git a/Source/CTest/Curl/arpa_telnet.h b/Source/CTest/Curl/arpa_telnet.h index 52ac66b..2cf0241 100644 --- a/Source/CTest/Curl/arpa_telnet.h +++ b/Source/CTest/Curl/arpa_telnet.h @@ -1,28 +1,28 @@ #ifndef __ARPA_TELNET_H #define __ARPA_TELNET_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ - + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET /* * Telnet option defines. Add more here if in need. */ @@ -97,5 +97,5 @@ static const char *telnetcmds[]= #define TELCMD_OK(x) ( ((unsigned int)(x) >= TELCMD_MINIMUM) && \ ((unsigned int)(x) <= TELCMD_MAXIMUM) ) #define TELCMD(x) telnetcmds[(x)-TELCMD_MINIMUM] - +#endif #endif diff --git a/Source/CTest/Curl/base64.c b/Source/CTest/Curl/base64.c index af4beb2..41c451a 100644 --- a/Source/CTest/Curl/base64.c +++ b/Source/CTest/Curl/base64.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Andrew Francis and Daniel Stenberg - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* Base64 encoding/decoding * diff --git a/Source/CTest/Curl/base64.h b/Source/CTest/Curl/base64.h index 55f86d5..5bda7d6 100644 --- a/Source/CTest/Curl/base64.h +++ b/Source/CTest/Curl/base64.h @@ -1,27 +1,27 @@ #ifndef __BASE64_H #define __BASE64_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ int Curl_base64_encode(const void *data, int size, char **str); int Curl_base64_decode(const char *str, void *data); #endif diff --git a/Source/CTest/Curl/ca-bundle.h b/Source/CTest/Curl/ca-bundle.h new file mode 100644 index 0000000..1545372 --- /dev/null +++ b/Source/CTest/Curl/ca-bundle.h @@ -0,0 +1,31 @@ +#ifndef __CA_BUNDLE_H +#define __CA_BUNDLE_H +/***************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * In order to be useful for every potential user, curl and libcurl are + * dual-licensed under the MPL and the MIT/X-derivate licenses. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the MPL or the MIT/X-derivate + * licenses. You may pick one of these licenses. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + *****************************************************************************/ + +#ifndef CURL_CA_BUNDLE +/* Set this to the full path file name of the ca cert bundle */ +#undef CURL_CA_BUNDLE +#endif + +#endif /* __CA_BUNDLE_H */ diff --git a/Source/CTest/Curl/config.h.in b/Source/CTest/Curl/config.h.in index 50d0a78..9a61b06 100644 --- a/Source/CTest/Curl/config.h.in +++ b/Source/CTest/Curl/config.h.in @@ -1,33 +1,33 @@ -/* lib/config.h.in. Generated automatically from configure.in by autoheader. */ +/* lib/config.h.in. Generated from configure.in by autoheader. */ /* Name of this package! */ -#define PACKAGE "${PACKAGE}" +#cmakedefine PACKAGE "${PACKAGE}" /* Version number of this archive. */ -#define VERSION "${VERSION}" +#cmakedefine VERSION "${VERSION}" /* Define if you have the getpass function. */ -#cmakedefine HAVE_GETPASS ${HAVE_GETPASS} +#cmakedefine HAVE_GETPASS ${HAVE_GETPASS} /* Define cpu-machine-OS */ -#define OS "${OPERATING_SYSTEM}" +#define OS "${OPERATING_SYSTEM}" /* Define if you have the gethostbyaddr_r() function with 5 arguments */ -#cmakedefine HAVE_GETHOSTBYADDR_R_5 ${HAVE_GETHOSTBYADDR_R_5} +#cmakedefine HAVE_GETHOSTBYADDR_R_5 ${HAVE_GETHOSTBYADDR_R_5} /* Define if you have the gethostbyaddr_r() function with 7 arguments */ -#cmakedefine HAVE_GETHOSTBYADDR_R_7 ${HAVE_GETHOSTBYADDR_R_7} +#cmakedefine HAVE_GETHOSTBYADDR_R_7 ${HAVE_GETHOSTBYADDR_R_7} /* Define if you have the gethostbyaddr_r() function with 8 arguments */ -#cmakedefine HAVE_GETHOSTBYADDR_R_8 ${HAVE_GETHOSTBYADDR_R_8} +#cmakedefine HAVE_GETHOSTBYADDR_R_8 ${HAVE_GETHOSTBYADDR_R_8} /* Define if you have the gethostbyname_r() function with 3 arguments */ -#cmakedefine HAVE_GETHOSTBYNAME_R_3 ${HAVE_GETHOSTBYNAME_R_3} +#cmakedefine HAVE_GETHOSTBYNAME_R_3 ${HAVE_GETHOSTBYNAME_R_3} /* Define if you have the gethostbyname_r() function with 5 arguments */ -#cmakedefine HAVE_GETHOSTBYNAME_R_5 ${HAVE_GETHOSTBYNAME_R_5} +#cmakedefine HAVE_GETHOSTBYNAME_R_5 ${HAVE_GETHOSTBYNAME_R_5} /* Define if you have the gethostbyname_r() function with 6 arguments */ -#cmakedefine HAVE_GETHOSTBYNAME_R_6 ${HAVE_GETHOSTBYNAME_R_6} +#cmakedefine HAVE_GETHOSTBYNAME_R_6 ${HAVE_GETHOSTBYNAME_R_6} /* Define if you have the inet_ntoa_r function declared. */ #cmakedefine HAVE_INET_NTOA_R_DECL ${HAVE_INET_NTOA_R_DECL} @@ -36,342 +36,433 @@ #cmakedefine HAVE_GETSERVBYNAME ${HAVE_GETSERVBYNAME} /* Define if you need the _REENTRANT define for some functions */ -#cmakedefine NEED_REENTRANT ${NEED_REENTRANT} +#cmakedefine NEED_REENTRANT ${NEED_REENTRANT} /* Define if you have the Kerberos4 libraries (including -ldes) */ -#cmakedefine KRB4 ${KRB4} +#cmakedefine KRB4 ${KRB4} /* Define if you want to enable IPv6 support */ -#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6} +#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6} /* Define this to 'int' if ssize_t is not an available typedefed type */ -#cmakedefine ssize_t ${ssize_t} +#cmakedefine ssize_t ${ssize_t} /* Define this to 'int' if socklen_t is not an available typedefed type */ -#cmakedefine socklen_t ${socklen_t} +#cmakedefine socklen_t ${socklen_t} /* Define this as a suitable file to read random data from */ #cmakedefine RANDOM_FILE "${RANDOM_FILE}" /* Define this to your Entropy Gathering Daemon socket pathname */ -#cmakedefine EGD_SOCKET ${EGD_SOCKET} +#cmakedefine EGD_SOCKET ${EGD_SOCKET} /* Define if you have a working OpenSSL installation */ -#cmakedefine OPENSSL_ENABLED ${OPENSSL_ENABLED} +#cmakedefine OPENSSL_ENABLED ${OPENSSL_ENABLED} /* Define the one correct non-blocking socket method below */ -#cmakedefine HAVE_FIONBIO ${HAVE_FIONBIO} -#cmakedefine HAVE_IOCTLSOCKET ${HAVE_IOCTLSOCKET} -#cmakedefine HAVE_IOCTLSOCKET_CASE ${HAVE_IOCTLSOCKET_CASE} -#cmakedefine HAVE_O_NONBLOCK ${HAVE_O_NONBLOCK} -#cmakedefine HAVE_DISABLED_NONBLOCKING ${HAVE_DISABLED_NONBLOCKING} +#cmakedefine HAVE_FIONBIO ${HAVE_FIONBIO} +#cmakedefine HAVE_IOCTLSOCKET ${HAVE_IOCTLSOCKET} +#cmakedefine HAVE_IOCTLSOCKET_CASE ${HAVE_IOCTLSOCKET_CASE} +#cmakedefine HAVE_O_NONBLOCK ${HAVE_O_NONBLOCK} +#cmakedefine HAVE_DISABLED_NONBLOCKING ${HAVE_DISABLED_NONBLOCKING} /* Define this to 'int' if in_addr_t is not an available typedefed type */ -#cmakedefine in_addr_t ${in_addr_t} +#cmakedefine in_addr_t ${in_addr_t} + +/* Define to disable DICT */ +#cmakedefine CURL_DISABLE_DICT ${CURL_DISABLE_DICT} + +/* Define to disable FILE */ +#cmakedefine CURL_DISABLE_FILE ${CURL_DISABLE_FILE} + +/* Define to disable FTP */ +#cmakedefine CURL_DISABLE_FTP ${CURL_DISABLE_FTP} + +/* Define to disable GOPHER */ +#cmakedefine CURL_DISABLE_GOPHER ${CURL_DISABLE_GOPHER} + +/* Define to disable HTTP */ +#cmakedefine CURL_DISABLE_HTTP ${CURL_DISABLE_HTTP} + +/* Define to disable LDAP */ +#cmakedefine CURL_DISABLE_LDAP ${CURL_DISABLE_LDAP} + +/* Define to disable TELNET */ +#cmakedefine CURL_DISABLE_TELNET ${CURL_DISABLE_TELNET} + +/* Define if you have zlib present */ +#cmakedefine HAVE_LIBZ ${HAVE_LIBZ} + +/* CA bundle full path name */ +#cmakedefine CURL_CA_BUNDLE ${CURL_CA_BUNDLE} + +/* to disable FILE */ +#cmakedefine CURL_DISABLE_FILE ${CURL_DISABLE_FILE} + +/* to disable FTP */ +#cmakedefine CURL_DISABLE_FTP ${CURL_DISABLE_FTP} + +/* to disable GOPHER */ +#cmakedefine CURL_DISABLE_GOPHER ${CURL_DISABLE_GOPHER} + +/* to disable HTTP */ +#cmakedefine CURL_DISABLE_HTTP ${CURL_DISABLE_HTTP} + +/* to disable LDAP */ +#cmakedefine CURL_DISABLE_LDAP ${CURL_DISABLE_LDAP} + +/* to disable TELNET */ +#cmakedefine CURL_DISABLE_TELNET ${CURL_DISABLE_TELNET} /* Set to explicitly specify we don't want to use thread-safe functions */ -#cmakedefine DISABLED_THREADSAFE ${DISABLED_THREADSAFE} +#cmakedefine DISABLED_THREADSAFE ${DISABLED_THREADSAFE} + +/* your Entropy Gathering Daemon socket pathname */ +#cmakedefine EGD_SOCKET ${EGD_SOCKET} /* Define if you want to enable IPv6 support */ -#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6} +#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6} + +/* Define to 1 if you have the <alloca.h> header file. */ +#cmakedefine HAVE_ALLOCA_H ${HAVE_ALLOCA_H} -/* Define if you have the <alloca.h> header file. */ -#cmakedefine HAVE_ALLOCA_H ${HAVE_ALLOCA_H} +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#cmakedefine HAVE_ARPA_INET_H ${HAVE_ARPA_INET_H} -/* Define if you have the <arpa/inet.h> header file. */ -#cmakedefine HAVE_ARPA_INET_H ${HAVE_ARPA_INET_H} +/* Define to 1 if you have the `closesocket' function. */ +#cmakedefine HAVE_CLOSESOCKET ${HAVE_CLOSESOCKET} -/* Define if you have the `closesocket' function. */ -#cmakedefine HAVE_CLOSESOCKET ${HAVE_CLOSESOCKET} +/* Define to 1 if you have the <crypto.h> header file. */ +#cmakedefine HAVE_CRYPTO_H ${HAVE_CRYPTO_H} -/* Define if you have the <crypto.h> header file. */ -#cmakedefine HAVE_CRYPTO_H ${HAVE_CRYPTO_H} +/* Define to 1 if you have the <des.h> header file. */ +#cmakedefine HAVE_DES_H ${HAVE_DES_H} -/* Define if you have the <des.h> header file. */ -#cmakedefine HAVE_DES_H ${HAVE_DES_H} +/* to disable NON-BLOCKING connections */ +#cmakedefine HAVE_DISABLED_NONBLOCKING ${HAVE_DISABLED_NONBLOCKING} -/* Define if you have the <dlfcn.h> header file. */ -#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H} +/* Define to 1 if you have the <dlfcn.h> header file. */ +#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H} -/* Define if you have the `dlopen' function. */ -#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN} +/* Define to 1 if you have the `dlopen' function. */ +#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN} -/* Define if you have the <err.h> header file. */ -#cmakedefine HAVE_ERR_H ${HAVE_ERR_H} +/* Define to 1 if you have the <err.h> header file. */ +#cmakedefine HAVE_ERR_H ${HAVE_ERR_H} -/* Define if you have the <fcntl.h> header file. */ -#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} +/* Define to 1 if you have the <fcntl.h> header file. */ +#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} /* Define if getaddrinfo exists and works */ -#cmakedefine HAVE_GETADDRINFO ${HAVE_GETADDRINFO} +#cmakedefine HAVE_GETADDRINFO ${HAVE_GETADDRINFO} -/* Define if you have the `geteuid' function. */ -#cmakedefine HAVE_GETEUID ${HAVE_GETEUID} +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID ${HAVE_GETEUID} -/* Define if you have the `gethostbyaddr' function. */ -#cmakedefine HAVE_GETHOSTBYADDR ${HAVE_GETHOSTBYADDR} +/* Define to 1 if you have the `gethostbyaddr' function. */ +#cmakedefine HAVE_GETHOSTBYADDR ${HAVE_GETHOSTBYADDR} -/* Define if you have the `gethostbyaddr_r' function. */ -#cmakedefine HAVE_GETHOSTBYADDR_R ${HAVE_GETHOSTBYADDR_R} +/* Define to 1 if you have the `gethostbyaddr_r' function. */ +#cmakedefine HAVE_GETHOSTBYADDR_R ${HAVE_GETHOSTBYADDR_R} -/* Define if you have the `gethostbyname_r' function. */ -#cmakedefine HAVE_GETHOSTBYNAME_R ${HAVE_GETHOSTBYNAME_R} +/* Define to 1 if you have the `gethostbyname_r' function. */ +#cmakedefine HAVE_GETHOSTBYNAME_R ${HAVE_GETHOSTBYNAME_R} -/* Define if you have the `gethostname' function. */ -#cmakedefine HAVE_GETHOSTNAME ${HAVE_GETHOSTNAME} +/* Define to 1 if you have the `getpass_r' function. */ +#cmakedefine HAVE_GETPASS_R ${HAVE_GETPASS_R} -/* Define if you have the `getpass_r' function. */ -#cmakedefine HAVE_GETPASS_R ${HAVE_GETPASS_R} +/* Define to 1 if you have the `getpwuid' function. */ +#cmakedefine HAVE_GETPWUID ${HAVE_GETPWUID} -/* Define if you have the `getpwuid' function. */ -#cmakedefine HAVE_GETPWUID ${HAVE_GETPWUID} +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} -/* Define if you have the `gettimeofday' function. */ -#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R ${HAVE_GMTIME_R} -/* Define if you have the `gmtime_r' function. */ -#cmakedefine HAVE_GMTIME_R ${HAVE_GMTIME_R} +/* Define to 1 if you have the `inet_addr' function. */ +#cmakedefine HAVE_INET_ADDR ${HAVE_INET_ADDR} -/* Define if you have the `inet_addr' function. */ -#cmakedefine HAVE_INET_ADDR ${HAVE_INET_ADDR} +/* Define to 1 if you have the `inet_ntoa' function. */ +#cmakedefine HAVE_INET_NTOA ${HAVE_INET_NTOA} -/* Define if you have the `inet_ntoa' function. */ -#cmakedefine HAVE_INET_NTOA ${HAVE_INET_NTOA} +/* Define to 1 if you have the `inet_ntoa_r' function. */ +#cmakedefine HAVE_INET_NTOA_R ${HAVE_INET_NTOA_R} -/* Define if you have the `inet_ntoa_r' function. */ -#cmakedefine HAVE_INET_NTOA_R ${HAVE_INET_NTOA_R} +/* Define to 1 if you have the <inttypes.h> header file. */ +#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} -/* Define if you have the <inttypes.h> header file. */ -#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} +/* Define to 1 if you have the <io.h> header file. */ +#cmakedefine HAVE_IO_H ${HAVE_IO_H} -/* Define if you have the <io.h> header file. */ -#cmakedefine HAVE_IO_H ${HAVE_IO_H} +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM ${HAVE_KRB_GET_OUR_IP_FOR_REALM} -/* Define if you have the `krb_get_our_ip_for_realm' function. */ -#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM ${HAVE_KRB_GET_OUR_IP_FOR_REALM} -/* Define if you have the <krb.h> header file. */ -#cmakedefine HAVE_KRB_H ${HAVE_KRB_H} +/* Define to 1 if you have the <krb.h> header file. */ +#cmakedefine HAVE_KRB_H ${HAVE_KRB_H} -/* Define if you have the `crypto' library (-lcrypto). */ -#cmakedefine HAVE_LIBCRYPTO ${HAVE_LIBCRYPTO} +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#cmakedefine HAVE_LIBCRYPTO ${HAVE_LIBCRYPTO} -/* Define if you have the `dl' library (-ldl). */ -#cmakedefine HAVE_LIBDL ${HAVE_LIBDL} +/* Define to 1 if you have the `dl' library (-ldl). */ +#cmakedefine HAVE_LIBDL ${HAVE_LIBDL} -/* Define if you have the `nsl' library (-lnsl). */ -#cmakedefine HAVE_LIBNSL ${HAVE_LIBNSL} +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#cmakedefine HAVE_LIBNSL ${HAVE_LIBNSL} -/* Define if you have the `resolv' library (-lresolv). */ -#cmakedefine HAVE_LIBRESOLV ${HAVE_LIBRESOLV} +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#cmakedefine HAVE_LIBRESOLV ${HAVE_LIBRESOLV} -/* Define if you have the `resolve' library (-lresolve). */ -#cmakedefine HAVE_LIBRESOLVE ${HAVE_LIBRESOLVE} +/* Define to 1 if you have the `resolve' library (-lresolve). */ +#cmakedefine HAVE_LIBRESOLVE ${HAVE_LIBRESOLVE} -/* Define if you have the `socket' library (-lsocket). */ -#cmakedefine HAVE_LIBSOCKET ${HAVE_LIBSOCKET} +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET ${HAVE_LIBSOCKET} -/* Define if you have the `ssl' library (-lssl). */ -#cmakedefine HAVE_LIBSSL ${HAVE_LIBSSL} +/* Define to 1 if you have the `ssl' library (-lssl). */ +#cmakedefine HAVE_LIBSSL ${HAVE_LIBSSL} -/* Define if you have the `ucb' library (-lucb). */ +/* Define to 1 if you have the `ucb' library (-lucb). */ #cmakedefine HAVE_LIBUCB ${HAVE_LIBUCB} -/* Define if you have the `localtime_r' function. */ -#cmakedefine HAVE_LOCALTIME_R ${HAVE_LOCALTIME_R} +/* If zlib is available */ +#cmakedefine HAVE_LIBZ ${HAVE_LIBZ} + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R ${HAVE_LOCALTIME_R} + +/* Define to 1 if you have the <malloc.h> header file. */ +#cmakedefine HAVE_MALLOC_H ${HAVE_MALLOC_H} + +/* Define to 1 if you have the <memory.h> header file. */ +#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} + +/* Define to 1 if you have the <netdb.h> header file. */ +#cmakedefine HAVE_NETDB_H ${HAVE_NETDB_H} + +/* Define to 1 if you have the <netinet/if_ether.h> header file. */ +#cmakedefine HAVE_NETINET_IF_ETHER_H ${HAVE_NETINET_IF_ETHER_H} + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#cmakedefine HAVE_NETINET_IN_H ${HAVE_NETINET_IN_H} -/* Define if you have the <malloc.h> header file. */ -#cmakedefine HAVE_MALLOC_H ${HAVE_MALLOC_H} +/* Define to 1 if you have the <net/if.h> header file. */ +#cmakedefine HAVE_NET_IF_H ${HAVE_NET_IF_H} -/* Define if you have the <memory.h> header file. */ -#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} +/* Define to 1 if you have the <openssl/crypto.h> header file. */ +#cmakedefine HAVE_OPENSSL_CRYPTO_H ${HAVE_OPENSSL_CRYPTO_H} -/* Define if you have the <netdb.h> header file. */ -#cmakedefine HAVE_NETDB_H ${HAVE_NETDB_H} +/* Define to 1 if you have the <openssl/engine.h> header file. */ +#cmakedefine HAVE_OPENSSL_ENGINE_H ${HAVE_OPENSSL_ENGINE_H} -/* Define if you have the <netinet/if_ether.h> header file. */ -#cmakedefine HAVE_NETINET_IF_ETHER_H ${HAVE_NETINET_IF_ETHER_H} +/* Define to 1 if you have the <openssl/err.h> header file. */ +#cmakedefine HAVE_OPENSSL_ERR_H ${HAVE_OPENSSL_ERR_H} -/* Define if you have the <netinet/in.h> header file. */ -#cmakedefine HAVE_NETINET_IN_H ${HAVE_NETINET_IN_H} +/* Define to 1 if you have the <openssl/pem.h> header file. */ +#cmakedefine HAVE_OPENSSL_PEM_H ${HAVE_OPENSSL_PEM_H} -/* Define if you have the <net/if.h> header file. */ -#cmakedefine HAVE_NET_IF_H ${HAVE_NET_IF_H} +/* Define to 1 if you have the <openssl/rsa.h> header file. */ +#cmakedefine HAVE_OPENSSL_RSA_H ${HAVE_OPENSSL_RSA_H} -/* Define if you have the <openssl/crypto.h> header file. */ -#cmakedefine HAVE_OPENSSL_CRYPTO_H ${HAVE_OPENSSL_CRYPTO_H} +/* Define to 1 if you have the <openssl/ssl.h> header file. */ +#cmakedefine HAVE_OPENSSL_SSL_H ${HAVE_OPENSSL_SSL_H} -/* Define if you have the <openssl/engine.h> header file. */ -#cmakedefine HAVE_OPENSSL_ENGINE_H ${HAVE_OPENSSL_ENGINE_H} +/* Define to 1 if you have the <openssl/x509.h> header file. */ +#cmakedefine HAVE_OPENSSL_X509_H ${HAVE_OPENSSL_X509_H} -/* Define if you have the <openssl/err.h> header file. */ -#cmakedefine HAVE_OPENSSL_ERR_H ${HAVE_OPENSSL_ERR_H} +/* Define to 1 if you have the <pem.h> header file. */ +#cmakedefine HAVE_PEM_H ${HAVE_PEM_H} -/* Define if you have the <openssl/pem.h> header file. */ -#cmakedefine HAVE_OPENSSL_PEM_H ${HAVE_OPENSSL_PEM_H} +/* Define to 1 if you have the `perror' function. */ +#cmakedefine HAVE_PERROR ${HAVE_PERROR} -/* Define if you have the <openssl/rsa.h> header file. */ -#cmakedefine HAVE_OPENSSL_RSA_H ${HAVE_OPENSSL_RSA_H} +/* Define to 1 if you have the `poll' function. */ +#cmakedefine HAVE_POLL ${HAVE_POLL} -/* Define if you have the <openssl/ssl.h> header file. */ -#cmakedefine HAVE_OPENSSL_SSL_H ${HAVE_OPENSSL_SSL_H} +/* Define to 1 if you have the <pwd.h> header file. */ +#cmakedefine HAVE_PWD_H ${HAVE_PWD_H} -/* Define if you have the <openssl/x509.h> header file. */ -#cmakedefine HAVE_OPENSSL_X509_H ${HAVE_OPENSSL_X509_H} +/* Define to 1 if you have the `RAND_egd' function. */ +#cmakedefine HAVE_RAND_EGD ${HAVE_RAND_EGD} -/* Define if you have the <pem.h> header file. */ -#cmakedefine HAVE_PEM_H ${HAVE_PEM_H} +/* Define to 1 if you have the `RAND_screen' function. */ +#cmakedefine HAVE_RAND_SCREEN ${HAVE_RAND_SCREEN} -/* Define if you have the `perror' function. */ -#cmakedefine HAVE_PERROR ${HAVE_PERROR} +/* Define to 1 if you have the `RAND_status' function. */ +#cmakedefine HAVE_RAND_STATUS ${HAVE_RAND_STATUS} -/* Define if you have the <pwd.h> header file. */ -#cmakedefine HAVE_PWD_H ${HAVE_PWD_H} +/* Define to 1 if you have the <rsa.h> header file. */ +#cmakedefine HAVE_RSA_H ${HAVE_RSA_H} -/* Define if you have the `RAND_egd' function. */ -#cmakedefine HAVE_RAND_EGD ${HAVE_RAND_EGD} +/* Define to 1 if you have the `select' function. */ +#cmakedefine HAVE_SELECT ${HAVE_SELECT} -/* Define if you have the `RAND_screen' function. */ -#cmakedefine HAVE_RAND_SCREEN ${HAVE_RAND_SCREEN} +/* Define to 1 if you have the <setjmp.h> header file. */ +#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H} -/* Define if you have the `RAND_status' function. */ -#cmakedefine HAVE_RAND_STATUS ${HAVE_RAND_STATUS} +/* Define to 1 if you have the `setvbuf' function. */ +#cmakedefine HAVE_SETVBUF ${HAVE_SETVBUF} -/* Define if you have the <rsa.h> header file. */ -#cmakedefine HAVE_RSA_H ${HAVE_RSA_H} +/* Define to 1 if you have the <sgtty.h> header file. */ +#cmakedefine HAVE_SGTTY_H ${HAVE_SGTTY_H} -/* Define if you have the `select' function. */ -#cmakedefine HAVE_SELECT ${HAVE_SELECT} +/* Define to 1 if you have the `sigaction' function. */ +#cmakedefine HAVE_SIGACTION ${HAVE_SIGACTION} -/* Define if you have the `setvbuf' function. */ -#cmakedefine HAVE_SETVBUF ${HAVE_SETVBUF} +/* Define to 1 if you have the `signal' function. */ +#cmakedefine HAVE_SIGNAL ${HAVE_SIGNAL} -/* Define if you have the <sgtty.h> header file. */ -#cmakedefine HAVE_SGTTY_H ${HAVE_SGTTY_H} +/* If you have sigsetjmp */ +#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP} -/* Define if you have the `sigaction' function. */ -#cmakedefine HAVE_SIGACTION ${HAVE_SIGACTION} +/* Define to 1 if you have the `socket' function. */ +#cmakedefine HAVE_SOCKET ${HAVE_SOCKET} -/* Define if you have the `signal' function. */ -#cmakedefine HAVE_SIGNAL ${HAVE_SIGNAL} +/* Define to 1 if you have the <ssl.h> header file. */ +#cmakedefine HAVE_SSL_H ${HAVE_SSL_H} -/* Define if you have the `socket' function. */ -#cmakedefine HAVE_SOCKET ${HAVE_SOCKET} +/* Define to 1 if you have the <stdint.h> header file. */ +#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} -/* Define if you have the <ssl.h> header file. */ -#cmakedefine HAVE_SSL_H ${HAVE_SSL_H} +/* Define to 1 if you have the <stdlib.h> header file. */ +#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} -/* Define if you have the <stdint.h> header file. */ -#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} +/* Define to 1 if you have the `strcasecmp' function. */ +#cmakedefine HAVE_STRCASECMP ${HAVE_STRCASECMP} -/* Define if you have the <stdlib.h> header file. */ -#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} +/* Define to 1 if you have the `strcmpi' function. */ +#cmakedefine HAVE_STRCMPI ${HAVE_STRCMPI} -/* Define if you have the `strcasecmp' function. */ -#cmakedefine HAVE_STRCASECMP ${HAVE_STRCASECMP} +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine HAVE_STRDUP ${HAVE_STRDUP} -/* Define if you have the `strcmpi' function. */ -#cmakedefine HAVE_STRCMPI ${HAVE_STRCMPI} +/* Define to 1 if you have the `strftime' function. */ +#cmakedefine HAVE_STRFTIME ${HAVE_STRFTIME} -/* Define if you have the `strdup' function. */ -#cmakedefine HAVE_STRDUP ${HAVE_STRDUP} +/* Define to 1 if you have the `stricmp' function. */ +#cmakedefine HAVE_STRICMP ${HAVE_STRICMP} -/* Define if you have the `strftime' function. */ -#cmakedefine HAVE_STRFTIME ${HAVE_STRFTIME} +/* Define to 1 if you have the <strings.h> header file. */ +#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H} -/* Define if you have the `stricmp' function. */ -#cmakedefine HAVE_STRICMP ${HAVE_STRICMP} +/* Define to 1 if you have the <string.h> header file. */ +#cmakedefine HAVE_STRING_H ${HAVE_STRING_H} -/* Define if you have the <strings.h> header file. */ -#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H} +/* Define to 1 if you have the `strlcat' function. */ +#cmakedefine HAVE_STRLCAT ${HAVE_STRLCAT} -/* Define if you have the <string.h> header file. */ -#cmakedefine HAVE_STRING_H ${HAVE_STRING_H} +/* Define to 1 if you have the `strlcpy' function. */ +#cmakedefine HAVE_STRLCPY ${HAVE_STRLCPY} -/* Define if you have the `strlcat' function. */ -#cmakedefine HAVE_STRLCAT ${HAVE_STRLCAT} +/* Define to 1 if you have the `strstr' function. */ +#cmakedefine HAVE_STRSTR ${HAVE_STRSTR} -/* Define if you have the `strlcpy' function. */ -#cmakedefine HAVE_STRLCPY ${HAVE_STRLCPY} +/* Define to 1 if you have the `strtok_r' function. */ +#cmakedefine HAVE_STRTOK_R ${HAVE_STRTOK_R} -/* Define if you have the `strstr' function. */ -#cmakedefine HAVE_STRSTR ${HAVE_STRSTR} +/* Define to 1 if you have the <sys/param.h> header file. */ +#cmakedefine HAVE_SYS_PARAM_H ${HAVE_SYS_PARAM_H} -/* Define if you have the `strtok_r' function. */ -#cmakedefine HAVE_STRTOK_R ${HAVE_STRTOK_R} +/* Define to 1 if you have the <sys/poll.h> header file. */ +#cmakedefine HAVE_SYS_POLL_H ${HAVE_SYS_POLL_H} -/* Define if you have the <sys/param.h> header file. */ -#cmakedefine HAVE_SYS_PARAM_H ${HAVE_SYS_PARAM_H} +/* Define to 1 if you have the <sys/select.h> header file. */ +#cmakedefine HAVE_SYS_SELECT_H ${HAVE_SYS_SELECT_H} -/* Define if you have the <sys/select.h> header file. */ -#cmakedefine HAVE_SYS_SELECT_H ${HAVE_SYS_SELECT_H} +/* Define to 1 if you have the <sys/socket.h> header file. */ +#cmakedefine HAVE_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H} -/* Define if you have the <sys/socket.h> header file. */ -#cmakedefine HAVE_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H} +/* Define to 1 if you have the <sys/sockio.h> header file. */ +#cmakedefine HAVE_SYS_SOCKIO_H ${HAVE_SYS_SOCKIO_H} -/* Define if you have the <sys/sockio.h> header file. */ -#cmakedefine HAVE_SYS_SOCKIO_H ${HAVE_SYS_SOCKIO_H} +/* Define to 1 if you have the <sys/stat.h> header file. */ +#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H} -/* Define if you have the <sys/stat.h> header file. */ -#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H} +/* Define to 1 if you have the <sys/time.h> header file. */ +#cmakedefine HAVE_SYS_TIME_H ${HAVE_SYS_TIME_H} -/* Define if you have the <sys/time.h> header file. */ -#cmakedefine HAVE_SYS_TIME_H ${HAVE_SYS_TIME_H} +/* Define to 1 if you have the <sys/types.h> header file. */ +#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} -/* Define if you have the <sys/types.h> header file. */ -#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} +/* Define to 1 if you have the <sys/utime.h> header file. */ +#cmakedefine HAVE_SYS_UTIME_H ${HAVE_SYS_UTIME_H} -/* Define if you have the <sys/utime.h> header file. */ -#cmakedefine HAVE_SYS_UTIME_H ${HAVE_SYS_UTIME_H} +/* Define to 1 if you have the `tcgetattr' function. */ +#cmakedefine HAVE_TCGETATTR ${HAVE_TCGETATTR} -/* Define if you have the `tcgetattr' function. */ -#cmakedefine HAVE_TCGETATTR ${HAVE_TCGETATTR} +/* Define to 1 if you have the `tcsetattr' function. */ +#cmakedefine HAVE_TCSETATTR ${HAVE_TCSETATTR} -/* Define if you have the `tcsetattr' function. */ -#cmakedefine HAVE_TCSETATTR ${HAVE_TCSETATTR} +/* Define to 1 if you have the <termios.h> header file. */ +#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} -/* Define if you have the <termios.h> header file. */ -#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} +/* Define to 1 if you have the <termio.h> header file. */ +#cmakedefine HAVE_TERMIO_H ${HAVE_TERMIO_H} -/* Define if you have the <termio.h> header file. */ -#cmakedefine HAVE_TERMIO_H ${HAVE_TERMIO_H} +/* Define to 1 if you have the <time.h> header file. */ +#cmakedefine HAVE_TIME_H ${HAVE_TIME_H} -/* Define if you have the <time.h> header file. */ -#cmakedefine HAVE_TIME_H ${HAVE_TIME_H} +/* Define to 1 if you have the `uname' function. */ +#cmakedefine HAVE_UNAME ${HAVE_UNAME} -/* Define if you have the `uname' function. */ -#cmakedefine HAVE_UNAME ${HAVE_UNAME} +/* Define to 1 if you have the <unistd.h> header file. */ +#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} -/* Define if you have the <unistd.h> header file. */ -#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} +/* Define to 1 if you have the `utime' function. */ +#cmakedefine HAVE_UTIME ${HAVE_UTIME} -/* Define if you have the `utime' function. */ -#cmakedefine HAVE_UTIME ${HAVE_UTIME} +/* Define to 1 if you have the <utime.h> header file. */ +#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H} -/* Define if you have the <utime.h> header file. */ -#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H} +/* Define to 1 if you have the <winsock.h> header file. */ +#cmakedefine HAVE_WINSOCK_H ${HAVE_WINSOCK_H} -/* Define if you have the <winsock.h> header file. */ -#cmakedefine HAVE_WINSOCK_H ${HAVE_WINSOCK_H} +/* Define to 1 if you have the <x509.h> header file. */ +#cmakedefine HAVE_X509_H ${HAVE_X509_H} -/* Define if you have the <x509.h> header file. */ -#cmakedefine HAVE_X509_H ${HAVE_X509_H} +/* if you have the zlib.h header file */ +#cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} + +/* if you have the Kerberos4 libraries (including -ldes) */ +#cmakedefine KRB4 ${KRB4} + +/* cpu-machine-OS */ +#define OS "${OPERATING_SYSTEM}" /* Name of package */ -#cmakedefine PACKAGE "${PACKAGE}" +#cmakedefine PACKAGE "${PACKAGE}" + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT} + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME "${PACKAGE_NAME}" + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING "${PACKAGE_STRING}" + +/* Define to the one symbol short name of this package. */ +#cmakedefine PACKAGE_TARNAME "${PACKAGE_TARNAME}" + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION "${PACKAGE_VERSION}" + +/* a suitable file to read random data from */ +#cmakedefine RANDOM_FILE "${RANDOM_FILE}" /* Define as the return type of signal handlers (`int' or `void'). */ -#cmakedefine RETSIGTYPE ${RETSIGTYPE} +#cmakedefine RETSIGTYPE ${RETSIGTYPE} -/* Define if you have the ANSI C header files. */ -#cmakedefine STDC_HEADERS ${STDC_HEADERS} +/* Define to 1 if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS ${STDC_HEADERS} -/* Define if you can safely include both <sys/time.h> and <time.h>. */ -#cmakedefine TIME_WITH_SYS_TIME ${TIME_WITH_SYS_TIME} +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#cmakedefine TIME_WITH_SYS_TIME ${TIME_WITH_SYS_TIME} /* Version number of package */ -#cmakedefine VERSION "${VERSION}" +#cmakedefine VERSION "${VERSION}" -/* Define if on AIX 3. +/* Define to 1 if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ #ifndef _ALL_SOURCE @@ -379,22 +470,22 @@ #endif /* Number of bits in a file offset, on hosts where this is settable. */ -#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} /* Define for large files, on AIX-style hosts. */ -#cmakedefine _LARGE_FILES ${_LARGE_FILES} +#cmakedefine _LARGE_FILES ${_LARGE_FILES} /* Define to empty if `const' does not conform to ANSI C. */ -#cmakedefine const ${const} +#cmakedefine const ${const} /* type to use in place of in_addr_t if not defined */ -#cmakedefine in_addr_t ${in_addr_t} +#cmakedefine in_addr_t ${in_addr_t} /* Define to `unsigned' if <sys/types.h> does not define. */ -#cmakedefine size_t ${size_t} +#cmakedefine size_t ${size_t} /* type to use in place of socklen_t if not defined */ -#cmakedefine socklen_t ${socklen_t} +#cmakedefine socklen_t ${socklen_t} /* Define to `int' if <sys/types.h> does not define. */ #cmakedefine ssize_t ${ssize_t} @@ -402,7 +493,7 @@ /* Define if you don't have vprintf but do have _doprnt. */ #cmakedefine HAVE_DOPRNT ${HAVE_DOPRNT} -/* Define if you have the vprintf function. */ +/* Define to 1 if you have the vprintf function. */ #cmakedefine HAVE_VPRINTF ${HAVE_VPRINTF} /* The number of bytes in a long double. */ diff --git a/Source/CTest/Curl/connect.c b/Source/CTest/Curl/connect.c index 77ceff0..eb6f4f3 100644 --- a/Source/CTest/Curl/connect.c +++ b/Source/CTest/Curl/connect.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -185,7 +185,6 @@ int waitconnect(int sockfd, /* socket */ return 0; } -#ifndef ENABLE_IPV6 static CURLcode bindlocal(struct connectdata *conn, int sockfd) { @@ -207,22 +206,28 @@ static CURLcode bindlocal(struct connectdata *conn, *************************************************************/ if (strlen(data->set.device)<255) { struct sockaddr_in sa; - struct hostent *h=NULL; - char *hostdataptr=NULL; + struct Curl_dns_entry *h=NULL; size_t size; char myhost[256] = ""; in_addr_t in; if(Curl_if2ip(data->set.device, myhost, sizeof(myhost))) { - h = Curl_resolv(data, myhost, 0, &hostdataptr); + /* + * We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer + */ + h = Curl_resolv(data, myhost, 0); } else { if(strlen(data->set.device)>1) { - h = Curl_resolv(data, data->set.device, 0, &hostdataptr); - } - if(h) { - /* we know data->set.device is shorter than the myhost array */ - strcpy(myhost, data->set.device); + /* + * This was not an interface, resolve the name as a host name + * or IP number + */ + h = Curl_resolv(data, data->set.device, 0); + if(h) { + /* we know data->set.device is shorter than the myhost array */ + strcpy(myhost, data->set.device); + } } } @@ -242,11 +247,19 @@ static CURLcode bindlocal(struct connectdata *conn, if (INADDR_NONE != in) { if ( h ) { + Curl_addrinfo *addr = h->addr; + + Curl_resolv_unlock(h); + /* we don't need it anymore after this function has returned */ + memset((char *)&sa, 0, sizeof(sa)); - memcpy((char *)&sa.sin_addr, - h->h_addr, - h->h_length); +#ifdef ENABLE_IPV6 + memcpy((char *)&sa.sin_addr, addr->ai_addr, addr->ai_addrlen); + sa.sin_family = addr->ai_family; +#else + memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); sa.sin_family = AF_INET; +#endif sa.sin_addr.s_addr = in; sa.sin_port = 0; /* get any port */ @@ -314,7 +327,7 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } -#endif /* end of ipv4-specific section */ + static int socketerror(int sockfd) @@ -330,21 +343,89 @@ int socketerror(int sockfd) } /* + * Curl_is_connected() is used from the multi interface to check if the + * firstsocket has connected. + */ + +CURLcode Curl_is_connected(struct connectdata *conn, + int sockfd, + bool *connected) +{ + int rc; + struct SessionHandle *data = conn->data; + + *connected = FALSE; /* a very negative world view is best */ + + if(data->set.timeout || data->set.connecttimeout) { + /* there is a timeout set */ + + /* Evaluate in milliseconds how much time that has passed */ + long has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start); + + /* subtract the most strict timeout of the ones */ + if(data->set.timeout && data->set.connecttimeout) { + if (data->set.timeout < data->set.connecttimeout) + has_passed -= data->set.timeout*1000; + else + has_passed -= data->set.connecttimeout*1000; + } + else if(data->set.timeout) + has_passed -= data->set.timeout*1000; + else + has_passed -= data->set.connecttimeout*1000; + + if(has_passed > 0 ) { + /* time-out, bail out, go home */ + failf(data, "Connection time-out"); + return CURLE_OPERATION_TIMEOUTED; + } + } + + /* check for connect without timeout as we want to return immediately */ + rc = waitconnect(sockfd, 0); + + if(0 == rc) { + int err = socketerror(sockfd); + if ((0 == err) || (EISCONN == err)) { + /* we are connected, awesome! */ + *connected = TRUE; + return CURLE_OK; + } + /* nope, not connected for real */ + if(err) + return CURLE_COULDNT_CONNECT; + } + + /* + * If the connection phase is "done" here, we should attempt to connect + * to the "next address" in the Curl_hostaddr structure that we resolved + * before. But we don't have that struct around anymore and we can't just + * keep a pointer since the cache might in fact have gotten pruned by the + * time we want to read this... Alas, we don't do this yet. + */ + + return CURLE_OK; +} + + +/* * TCP connect to the given host with timeout, proxy or remote doesn't matter. * There might be more than one IP address to try out. Fill in the passed * pointer with the connected socket. */ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ - Curl_addrinfo *remotehost, /* use one in here */ + struct Curl_dns_entry *remotehost, /* use this one */ int port, /* connect to this */ int *sockconn, /* the connected socket */ - Curl_ipconnect **addr) /* the one we used */ + Curl_ipconnect **addr, /* the one we used */ + bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; int rc; int sockfd=-1; int aliasindex=0; + char *hostname; struct timeval after; struct timeval before = Curl_tvnow(); @@ -353,6 +434,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ * Figure out what maximum time we have left *************************************************************/ long timeout_ms=300000; /* milliseconds, default to five minutes */ + + *connected = FALSE; /* default to not connected */ + if(data->set.timeout || data->set.connecttimeout) { double has_passed; @@ -385,6 +469,13 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } + hostname = data->change.proxy?conn->proxyhost:conn->hostname; + infof(data, "About to connect() to %s%s%s:%d\n", + conn->bits.ipv6_ip?"[":"", + hostname, + conn->bits.ipv6_ip?"]":"", + port); + #ifdef ENABLE_IPV6 /* * Connecting with IPv6 support is so much easier and cleanly done @@ -393,11 +484,19 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct addrinfo *ai; port =0; /* prevent compiler warning */ - for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) { + for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) continue; + if(conn->data->set.device) { + /* user selected to bind the outgoing socket to a specified "device" + before doing connect */ + CURLcode res = bindlocal(conn, sockfd); + if(res) + return res; + } + /* set socket non-blocking */ Curl_nonblock(sockfd, TRUE); @@ -417,17 +516,21 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ case EAGAIN: #endif case EINTR: - /* asynchronous connect, wait for connect or timeout */ + if(data->state.used_interface == Curl_if_multi) + /* don't hang when doing multi */ + timeout_ms = 0; + rc = waitconnect(sockfd, timeout_ms); break; case ECONNREFUSED: /* no one listening */ default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect"); + failf(data, "Failed connect to %s: %d", hostname, error); break; } } + if(0 == rc) { /* we might be connected, if the socket says it is OK! Ask it! */ int err; @@ -435,10 +538,17 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ err = socketerror(sockfd); if ((0 == err) || (EISCONN == err)) { /* we are connected, awesome! */ + *connected = TRUE; /* this is truly a connect */ break; } + failf(data, "socket error: %d", err); /* we are _not_ connected, it was a false alert, continue please */ } + else if(data->state.used_interface == Curl_if_multi) { + /* When running the multi interface, we bail out here */ + rc = 0; + break; + } /* connect failed or timed out */ sclose(sockfd); @@ -454,10 +564,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ before = after; continue; } - if (sockfd < 0) { - failf(data, "connect() failed"); + if (sockfd < 0) return CURLE_COULDNT_CONNECT; - } /* leave the socket in non-blocking mode */ @@ -468,7 +576,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* * Connecting with IPv4-only support */ - if(!remotehost->h_addr_list[0]) { + if(!remotehost->addr->h_addr_list[0]) { /* If there is no addresses in the address list, then we return error right away */ failf(data, "no address available"); @@ -495,17 +603,17 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* This is the loop that attempts to connect to all IP-addresses we know for the given host. One by one. */ for(rc=-1, aliasindex=0; - rc && (struct in_addr *)remotehost->h_addr_list[aliasindex]; + rc && (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; aliasindex++) { struct sockaddr_in serv_addr; /* do this nasty work to do the connect */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memcpy((char *)&(serv_addr.sin_addr), - (struct in_addr *)remotehost->h_addr_list[aliasindex], + (struct in_addr *)remotehost->addr->h_addr_list[aliasindex], sizeof(struct in_addr)); - serv_addr.sin_family = remotehost->h_addrtype; - serv_addr.sin_port = htons(port); + serv_addr.sin_family = remotehost->addr->h_addrtype; + serv_addr.sin_port = htons((unsigned short)port); rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); @@ -523,13 +631,17 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ */ case EAGAIN: #endif - /* asynchronous connect, wait for connect or timeout */ + if(data->state.used_interface == Curl_if_multi) + /* don't hang when doing multi */ + timeout_ms = 0; + rc = waitconnect(sockfd, timeout_ms); break; default: /* unknown error, fallthrough and try another address! */ - failf(data, "Failed to connect to IP number %d", aliasindex+1); + failf(data, "Failed to connect to %s IP number %d: %d", + hostname, aliasindex+1, error); break; } } @@ -538,6 +650,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int err = socketerror(sockfd); if ((0 == err) || (EISCONN == err)) { /* we are connected, awesome! */ + *connected = TRUE; /* this is a true connect */ break; } /* nope, not connected for real */ @@ -545,6 +658,12 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } if(0 != rc) { + if(data->state.used_interface == Curl_if_multi) { + /* When running the multi interface, we bail out here */ + rc = 0; + break; + } + /* get a new timeout for next attempt */ after = Curl_tvnow(); timeout_ms -= Curl_tvdiff(after, before); @@ -561,7 +680,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* no good connect was made */ sclose(sockfd); *sockconn = -1; - failf(data, "Couldn't connect to host"); + failf(data, "Connect failed"); return CURLE_COULDNT_CONNECT; } @@ -569,7 +688,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ if(addr) /* this is the address we've connected to */ - *addr = (struct in_addr *)remotehost->h_addr_list[aliasindex]; + *addr = (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; #endif /* allow NULL-pointers to get passed in */ diff --git a/Source/CTest/Curl/connect.h b/Source/CTest/Curl/connect.h index f8c10db..fdbecec 100644 --- a/Source/CTest/Curl/connect.h +++ b/Source/CTest/Curl/connect.h @@ -1,35 +1,40 @@ #ifndef __CONNECT_H #define __CONNECT_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ int Curl_nonblock(int socket, /* operate on this */ int nonblock /* TRUE or FALSE */); +CURLcode Curl_is_connected(struct connectdata *conn, + int sockfd, + bool *connected); + CURLcode Curl_connecthost(struct connectdata *conn, - Curl_addrinfo *host, /* connect to this */ + struct Curl_dns_entry *host, /* connect to this */ int port, /* connect to this port number */ int *sockconn, /* not set if error is returned */ - Curl_ipconnect **addr /* the one we used */ - ); /* index we used */ + Curl_ipconnect **addr, /* the one we used */ + bool *connected /* truly connected? */ + ); #endif diff --git a/Source/CTest/Curl/content_encoding.c b/Source/CTest/Curl/content_encoding.c new file mode 100644 index 0000000..80d9eec --- /dev/null +++ b/Source/CTest/Curl/content_encoding.c @@ -0,0 +1,122 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ + +#include "setup.h" + +#ifdef HAVE_LIBZ + +#include "urldata.h" +#include <curl/curl.h> +#include <curl/types.h> +#include "sendf.h" + +#define DSIZ 4096 /* buffer size for decompressed data */ + + +static CURLcode +process_zlib_error(struct SessionHandle *data, z_stream *z) +{ + if (z->msg) + failf (data, "Error while processing content unencoding.\n%s", + z->msg); + else + failf (data, "Error while processing content unencoding.\n" + "Unknown failure within decompression software."); + + return CURLE_BAD_CONTENT_ENCODING; +} + +static CURLcode +exit_zlib(z_stream *z, bool *zlib_init, CURLcode result) +{ + inflateEnd(z); + *zlib_init = 0; + return result; +} + +CURLcode +Curl_unencode_deflate_write(struct SessionHandle *data, + struct Curl_transfer_keeper *k, + ssize_t nread) +{ + int status; /* zlib status */ + int result; /* Curl_client_write status */ + char decomp[DSIZ]; /* Put the decompressed data here. */ + z_stream *z = &k->z; /* zlib state structure */ + + /* Initialize zlib? */ + if (!k->zlib_init) { + z->zalloc = (alloc_func)Z_NULL; + z->zfree = (free_func)Z_NULL; + z->opaque = 0; /* of dubious use 08/27/02 jhrg */ + if (inflateInit(z) != Z_OK) + return process_zlib_error(data, z); + k->zlib_init = 1; + } + + /* Set the compressed input when this fucntion is called */ + z->next_in = (Bytef *)k->str; + z->avail_in = nread; + + /* because the buffer size is fixed, iteratively decompress + and transfer to the client via client_write. */ + for (;;) { + /* (re)set buffer for decompressed output for every iteration */ + z->next_out = (Bytef *)&decomp[0]; + z->avail_out = DSIZ; + + status = inflate(z, Z_SYNC_FLUSH); + if (status == Z_OK || status == Z_STREAM_END) { + result = Curl_client_write(data, CLIENTWRITE_BODY, decomp, + DSIZ - z->avail_out); + /* if !CURLE_OK, clean up, return */ + if (result) { + return exit_zlib(z, &k->zlib_init, result); + } + + /* Done?; clean up, return */ + if (status == Z_STREAM_END) { + if (inflateEnd(z) == Z_OK) + return exit_zlib(z, &k->zlib_init, result); + else + return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z)); + } + + /* Done with these bytes, exit */ + if (status == Z_OK && z->avail_in == 0 && z->avail_out > 0) + return result; + } + else { /* Error; exit loop, handle below */ + return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z)); + } + } +} +#endif /* HAVE_LIBZ */ + +/* + * local variables: + * eval: (load-file "../curl-mode.el") + * end: + * vim600: fdm=marker + * vim: et sw=2 ts=2 sts=2 tw=78 + */ diff --git a/Source/CTest/Curl/content_encoding.h b/Source/CTest/Curl/content_encoding.h new file mode 100644 index 0000000..2e7676b --- /dev/null +++ b/Source/CTest/Curl/content_encoding.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ + +CURLcode Curl_unencode_deflate_write(struct SessionHandle *data, + struct Curl_transfer_keeper *k, + ssize_t nread); + +/* + * local variables: + * eval: (load-file "../curl-mode.el") + * end: + * vim600: fdm=marker + * vim: et sw=2 ts=2 sts=2 tw=78 + */ diff --git a/Source/CTest/Curl/cookie.c b/Source/CTest/Curl/cookie.c index 4593530..a5af458 100644 --- a/Source/CTest/Curl/cookie.c +++ b/Source/CTest/Curl/cookie.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /*** @@ -79,6 +79,8 @@ Example set of cookies: #include "setup.h" +#ifndef CURL_DISABLE_HTTP + #include <stdlib.h> #include <string.h> #include <ctype.h> @@ -93,6 +95,21 @@ Example set of cookies: #include "memdebug.h" #endif +static void +free_cookiemess(struct Cookie *co) +{ + if(co->domain) + free(co->domain); + if(co->path) + free(co->path); + if(co->name) + free(co->name); + if(co->value) + free(co->value); + + free(co); +} + /**************************************************************************** * * Curl_cookie_add() @@ -104,7 +121,7 @@ Example set of cookies: struct Cookie * Curl_cookie_add(struct CookieInfo *c, bool httpheader, /* TRUE if HTTP header-style line */ - char *lineptr, /* first non-space of the line */ + char *lineptr, /* first character of the line */ char *domain) /* default domain */ { struct Cookie *clist; @@ -129,6 +146,10 @@ Curl_cookie_add(struct CookieInfo *c, /* This line was read off a HTTP-header */ char *sep; semiptr=strchr(lineptr, ';'); /* first, find a semicolon */ + + while(*lineptr && isspace((int)*lineptr)) + lineptr++; + ptr = lineptr; do { /* we have a <what>=<this> pair or a 'secure' word here */ @@ -145,6 +166,8 @@ Curl_cookie_add(struct CookieInfo *c, name, what)) { /* this is a <name>=<what> pair */ + char *whatptr; + /* Strip off trailing whitespace from the 'what' */ int len=strlen(what); while(len && isspace((int)what[len-1])) { @@ -152,15 +175,21 @@ Curl_cookie_add(struct CookieInfo *c, len--; } + /* Skip leading whitespace from the 'what' */ + whatptr=what; + while(isspace((int)*whatptr)) { + whatptr++; + } + if(strequal("path", name)) { - co->path=strdup(what); + co->path=strdup(whatptr); } else if(strequal("domain", name)) { - co->domain=strdup(what); - co->field1= (what[0]=='.')?2:1; + co->domain=strdup(whatptr); + co->field1= (whatptr[0]=='.')?2:1; } else if(strequal("version", name)) { - co->version=strdup(what); + co->version=strdup(whatptr); } else if(strequal("max-age", name)) { /* Defined in RFC2109: @@ -172,17 +201,17 @@ Curl_cookie_add(struct CookieInfo *c, cookie should be discarded immediately. */ - co->maxage = strdup(what); + co->maxage = strdup(whatptr); co->expires = atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now; } else if(strequal("expires", name)) { - co->expirestr=strdup(what); + co->expirestr=strdup(whatptr); co->expires = curl_getdate(what, &now); } else if(!co->name) { co->name = strdup(name); - co->value = strdup(what); + co->value = strdup(whatptr); } /* else this is the second (or more) name we don't know @@ -318,22 +347,19 @@ Curl_cookie_add(struct CookieInfo *c, if(7 != fields) { /* we did not find the sufficient number of fields to recognize this as a valid line, abort and go home */ - - if(co->domain) - free(co->domain); - if(co->path) - free(co->path); - if(co->name) - free(co->name); - if(co->value) - free(co->value); - - free(co); + free_cookiemess(co); return NULL; } } + if(!c->running && /* read from a file */ + c->newsession && /* clean session cookies */ + !co->expires) { /* this is a session cookie since it doesn't expire! */ + free_cookiemess(co); + return NULL; + } + co->livecookie = c->running; /* now, we have parsed the incoming line, we must now check if this @@ -347,7 +373,13 @@ Curl_cookie_add(struct CookieInfo *c, /* the names are identical */ if(clist->domain && co->domain) { - if(strequal(clist->domain, co->domain)) + if(strequal(clist->domain, co->domain) || + (clist->domain[0]=='.' && + strequal(&(clist->domain[1]), co->domain)) || + (co->domain[0]=='.' && + strequal(clist->domain, &(co->domain[1]))) ) + /* The domains are identical, or at least identical if you skip the + preceeding dot */ replace_old=TRUE; } else if(!clist->domain && !co->domain) @@ -448,8 +480,12 @@ Curl_cookie_add(struct CookieInfo *c, * Inits a cookie struct to read data from a local file. This is always * called before any cookies are set. File may be NULL. * + * If 'newsession' is TRUE, discard all "session cookies" on read from file. + * ****************************************************************************/ -struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc) +struct CookieInfo *Curl_cookie_init(char *file, + struct CookieInfo *inc, + bool newsession) { char line[MAX_COOKIE_LINE]; struct CookieInfo *c; @@ -477,11 +513,13 @@ struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc) else fp = file?fopen(file, "r"):NULL; + c->newsession = newsession; /* new session? */ + if(fp) { char *lineptr; bool headerline; while(fgets(line, MAX_COOKIE_LINE, fp)) { - if(strnequal("Set-Cookie:", line, 11)) { + if(checkprefix("Set-Cookie:", line)) { /* This is a cookie line, get it! */ lineptr=&line[11]; headerline=TRUE; @@ -499,7 +537,7 @@ struct CookieInfo *Curl_cookie_init(char *file, struct CookieInfo *inc) fclose(fp); } - c->running = TRUE; /* now, we're running */ + c->running = TRUE; /* now, we're running */ return c; } @@ -549,8 +587,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, /* now check the left part of the path with the cookies path requirement */ - if(!co->path || - strnequal(path, co->path, strlen(co->path))) { + if(!co->path || + checkprefix(co->path, path) ) { /* and now, we know this is a match and we should create an entry for the return-linked-list */ @@ -729,6 +767,8 @@ int main(int argc, char **argv) #endif +#endif /* CURL_DISABLE_HTTP */ + /* * local variables: * eval: (load-file "../curl-mode.el") diff --git a/Source/CTest/Curl/cookie.h b/Source/CTest/Curl/cookie.h index f5eba37..77ac059 100644 --- a/Source/CTest/Curl/cookie.h +++ b/Source/CTest/Curl/cookie.h @@ -1,27 +1,27 @@ #ifndef __COOKIE_H #define __COOKIE_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include <stdio.h> #ifdef WIN32 @@ -55,9 +55,10 @@ struct CookieInfo { /* linked list of cookies we know of */ struct Cookie *cookies; - char *filename; /* file we read from/write to */ - bool running; /* state info, for cookie adding information */ + char *filename; /* file we read from/write to */ + bool running; /* state info, for cookie adding information */ long numcookies; /* number of cookies in the "jar" */ + bool newsession; /* new session, discard session cookies on load */ }; /* This is the maximum line length we accept for a cookie line */ @@ -75,7 +76,7 @@ struct CookieInfo { struct Cookie *Curl_cookie_add(struct CookieInfo *, bool header, char *line, char *domain); -struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *); +struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *, bool); struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool); void Curl_cookie_freelist(struct Cookie *); void Curl_cookie_cleanup(struct CookieInfo *); diff --git a/Source/CTest/Curl/curl/curl.h b/Source/CTest/Curl/curl/curl.h index b6bc3a6..c56c965 100644 --- a/Source/CTest/Curl/curl/curl.h +++ b/Source/CTest/Curl/curl/curl.h @@ -1,27 +1,27 @@ #ifndef __CURL_CURL_H #define __CURL_CURL_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include <stdio.h> /* The include stuff here is mainly for time_t! */ @@ -49,22 +49,31 @@ #define FALSE 0 #endif -#include <curl/types.h> +#include "types.h" #ifdef __cplusplus extern "C" { #endif -struct HttpPost { - struct HttpPost *next; /* next entry in the list */ +/* stupid #define trick to preserve functionality with older code, but + making it use our name space for the future */ +#define HttpPost curl_httppost + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ char *name; /* pointer to allocated name */ long namelength; /* length of name length */ char *contents; /* pointer to allocated data contents */ long contentslength; /* length of contents field */ + + /* CMC: Added support for buffer uploads */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ struct curl_slist* contentheader; /* list of extra headers for this form */ - struct HttpPost *more; /* if one field name has more than one file, this - link should link to following files */ + struct curl_httppost *more; /* if one field name has more than one file, this + link should link to following files */ long flags; /* as defined below */ #define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */ #define HTTPPOST_READFILE (1<<1) /* specified content is a file name */ @@ -72,6 +81,13 @@ struct HttpPost { do not free in formfree */ #define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer do not free in formfree */ + +/* CMC: Added support for buffer uploads */ +#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */ +#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */ + + char *showfilename; /* The file name to show. If not set, the actual + file name will be used (if this is a file part) */ }; typedef int (*curl_progress_callback)(void *clientp, @@ -80,6 +96,8 @@ typedef int (*curl_progress_callback)(void *clientp, double ultotal, double ulnow); +#define CURL_MAX_WRITE_SIZE 20480 + typedef size_t (*curl_write_callback)(char *buffer, size_t size, size_t nitems, @@ -95,6 +113,23 @@ typedef int (*curl_passwd_callback)(void *clientp, char *buffer, int buflen); +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userp); /* whatever the user please */ + /* All possible error codes from all sorts of curl functions. Future versions may return other values, stay prepared. @@ -139,7 +174,7 @@ typedef enum { CURLE_HTTP_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ CURLE_HTTP_POST_ERROR, /* 34 */ CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ - CURLE_FTP_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ CURLE_FILE_COULDNT_READ_FILE, /* 37 */ CURLE_LDAP_CANNOT_BIND, /* 38 */ CURLE_LDAP_SEARCH_FAILED, /* 39 */ @@ -157,11 +192,28 @@ typedef enum { CURLE_SSL_PEER_CERTIFICATE, /* 51 - peer's certificate wasn't ok */ CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ - CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as default */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_SHARE_IN_USE, /* 57 - share is in use */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized transfer encoding */ CURL_LAST /* never use! */ } CURLcode; +/* Make a spelling correction for the operation timed-out define */ +#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED + +typedef enum { + CURLPROXY_HTTP = 0, + CURLPROXY_SOCKS4 = 4, + CURLPROXY_SOCKS5 = 5 +} curl_proxytype; + /* this was the error code 50 in 7.7.3 and a few earlier versions, this is no longer used by libcurl but is instead #defined here only to not make programs break */ @@ -169,22 +221,47 @@ typedef enum { /* This is just to make older programs not break: */ #define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME #define CURL_ERROR_SIZE 256 +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 + /* name is uppercase CURLOPT_<name>, type is one of the defined CURLOPTTYPE_<type> number is unique identifier */ #ifdef CINIT #undef CINIT #endif -#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number +/* + * Figure out if we can use the ## operator, which is supported by ISO/ANSI C + * and C++. Some compilers support it without setting __STDC__ or __cplusplus + * so we need to carefully check for them too. We don't use configure-checks + * for these since we want these headers to remain generic and working for all + * platforms. + */ +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif -/* long may be 32 or 64 bits, but we should never depend on anything else - but 32 */ -#define CURLOPTTYPE_LONG 0 -#define CURLOPTTYPE_OBJECTPOINT 10000 -#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#ifdef CURL_ISOCPP +#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif typedef enum { CINIT(NOTHING, LONG, 0), /********* the first one is unused ************/ @@ -344,7 +421,11 @@ typedef enum { CINIT(FTPLISTONLY, LONG, 48), /* Use NLST when listing ftp dir */ CINIT(FTPAPPEND, LONG, 50), /* Append instead of overwrite on upload! */ - CINIT(NETRC, LONG, 51), /* read user+password from .netrc */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ /* This FTPASCII name is now obsolete, to be removed, use the TRANSFERTEXT @@ -496,10 +577,49 @@ typedef enum { /* send linked-list of pre-transfer QUOTE commands (Wesley Laxton)*/ CINIT(PREQUOTE, OBJECTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, OBJECTPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), - CURLOPT_LASTENTRY /* the last unusued */ + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_SOCKS4 and CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. */ + CINIT(ENCODING, OBJECTPOINT, 102), + + + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; + /* two convenient "aliases" that follow the name scheme better */ +#define CURLOPT_WRITEDATA CURLOPT_FILE +#define CURLOPT_READDATA CURLOPT_INFILE +#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ enum { CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd @@ -511,6 +631,18 @@ enum { CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ }; + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + enum { CURL_SSLVERSION_DEFAULT, CURL_SSLVERSION_TLSv1, @@ -522,15 +654,26 @@ enum { typedef enum { - TIMECOND_NONE, + CURL_TIMECOND_NONE, - TIMECOND_IFMODSINCE, - TIMECOND_IFUNMODSINCE, - TIMECOND_LASTMOD, + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, - TIMECOND_LAST + CURL_TIMECOND_LAST } curl_TimeCond; +/* for backwards compatibility */ +#ifndef TIMECOND_IFMODSINCE +#define TIMECOND_IFMODSINCE CURL_TIMECOND_IFMODSINCE +#endif +#ifndef TIMECOND_IFUNMODSINCE +#define TIMECOND_IFUNMODSINCE CURL_TIMECOND_IFUNMODSINCE +#endif +#ifndef TIMECOND_LASTMOD +#define TIMECOND_LASTMOD CURL_TIMECOND_LASTMOD +#endif + #ifdef __BEOS__ #include <support/SupportDefs.h> #endif @@ -548,16 +691,21 @@ extern int (curl_strnequal)(const char *s1, const char *s2, size_t n); #define strequal(a,b) curl_strequal(a,b) #define strnequal(a,b,c) curl_strnequal(a,b,c) -/* external form function */ -int curl_formparse(char *string, - struct HttpPost **httppost, - struct HttpPost **last_post); +/* DEPRECATED function to build formdata */ +int curl_formparse(char *, struct curl_httppost **, + struct curl_httppost **_post); /* name is uppercase CURLFORM_<name> */ #ifdef CFINIT #undef CFINIT #endif + +#ifdef CURL_ISOCPP #define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif typedef enum { CFINIT(NOTHING), /********* the first one is unused ************/ @@ -571,29 +719,65 @@ typedef enum { CFINIT(CONTENTSLENGTH), CFINIT(FILECONTENT), CFINIT(ARRAY), - CFINIT(ARRAY_START), /* below are the options allowed within a array */ + CFINIT(OBSOLETE), CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + CFINIT(CONTENTTYPE), CFINIT(CONTENTHEADER), + CFINIT(FILENAME), CFINIT(END), - CFINIT(ARRAY_END), /* up are the options allowed within a array */ + CFINIT(OBSOLETE2), CURLFORM_LASTENTRY /* the last unusued */ } CURLformoption; +#undef CFINIT /* done */ + /* structure to be used as parameter for CURLFORM_ARRAY */ struct curl_forms { CURLformoption option; const char *value; }; -/* new external form function */ -int curl_formadd(struct HttpPost **httppost, - struct HttpPost **last_post, +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, ...); /* cleanup a form: */ -void curl_formfree(struct HttpPost *form); +void curl_formfree(struct curl_httppost *form); /* Unix and Win32 getenv function call, this returns a malloc()'ed string that MUST be free()ed after usage is complete. */ @@ -606,6 +790,9 @@ char *curl_version(void); * allocated string or NULL if an error occurred. */ char *curl_escape(const char *string, int length); char *curl_unescape(const char *string, int length); +/* 20020912 WJM. Provide for a de-allocation in the same translation unit + that did the allocation. Added in libcurl 7.10 */ +void curl_free(void *p); /* curl_global_init() should be invoked exactly once for each application that uses libcurl */ @@ -616,8 +803,8 @@ CURLcode curl_global_init(long flags); void curl_global_cleanup(void); /* This is the version number */ -#define LIBCURL_VERSION "7.9.5" -#define LIBCURL_VERSION_NUM 0x070905 +#define LIBCURL_VERSION "7.10.2" +#define LIBCURL_VERSION_NUM 0x070a02 /* linked-list structure for the CURLOPT_QUOTE option (and other) */ struct curl_slist { @@ -671,14 +858,18 @@ typedef enum { CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + /* Fill in new entries here! */ - CURLINFO_LASTONE = 19 + CURLINFO_LASTONE = 21 } CURLINFO; -/* unfortunately, the easy.h include file needs the options and info stuff - before it can be included! */ -#include <curl/easy.h> /* nothing in curl is fun without the easy stuff */ +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" typedef enum { CURLCLOSEPOLICY_NONE, /* first, never use this */ @@ -698,6 +889,78 @@ typedef enum { #define CURL_GLOBAL_NOTHING 0 #define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different types of locks that a share can aquire */ +typedef enum { + CURL_LOCK_TYPE_NONE = 0, + CURL_LOCK_TYPE_COOKIE = 1<<0, + CURL_LOCK_TYPE_DNS = 1<<1, + CURL_LOCK_TYPE_SSL_SESSION = 2<<1, + CURL_LOCK_TYPE_CONNECT = 2<<2, + CURL_LOCK_TYPE_LAST +} curl_lock_type; + +typedef void (*curl_lock_function)(CURL *, curl_lock_type, void *); +typedef void (*curl_unlock_function)(CURL *, curl_lock_type, void *); + +typedef struct { + unsigned int specifier; + unsigned int locked; + unsigned int dirty; + + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *clientdata; +} curl_share; + +curl_share *curl_share_init (void); +CURLcode curl_share_setopt (curl_share *, curl_lock_type, int); +CURLcode curl_share_set_lock_function (curl_share *, curl_lock_function); +CURLcode curl_share_set_unlock_function (curl_share *, curl_unlock_function); +CURLcode curl_share_set_lock_data (curl_share *, void *); +CURLcode curl_share_destroy (curl_share *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basicly all programs ever, that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redfine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_FIRST + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + char *ssl_version; /* human readable string */ + long ssl_version_num; /* number */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char **protocols; +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) +#define CURL_VERSION_KERBEROS4 (1<<1) +#define CURL_VERSION_SSL (1<<2) +#define CURL_VERSION_LIBZ (1<<3) + +/* returns a pointer to a static copy of the version info struct */ +curl_version_info_data *curl_version_info(CURLversion); + #ifdef __cplusplus } #endif diff --git a/Source/CTest/Curl/curl/easy.h b/Source/CTest/Curl/curl/easy.h index d3545ff..47f4e96 100644 --- a/Source/CTest/Curl/curl/easy.h +++ b/Source/CTest/Curl/curl/easy.h @@ -1,27 +1,27 @@ #ifndef __CURL_EASY_H #define __CURL_EASY_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #ifdef __cplusplus extern "C" { #endif diff --git a/Source/CTest/Curl/curl/stdcheaders.h b/Source/CTest/Curl/curl/stdcheaders.h index 3fbaaf7..35648b5 100644 --- a/Source/CTest/Curl/curl/stdcheaders.h +++ b/Source/CTest/Curl/curl/stdcheaders.h @@ -1,27 +1,27 @@ #ifndef __STDC_HEADERS_H #define __STDC_HEADERS_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> diff --git a/Source/CTest/Curl/curl/types.h b/Source/CTest/Curl/curl/types.h index 05f73bf..5598880 100644 --- a/Source/CTest/Curl/curl/types.h +++ b/Source/CTest/Curl/curl/types.h @@ -1,27 +1,27 @@ #ifndef __CURL_TYPES_H #define __CURL_TYPES_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ typedef void CURL; typedef void CURLconnect; diff --git a/Source/CTest/Curl/dict.c b/Source/CTest/Curl/dict.c index d5068ff..94257c9 100644 --- a/Source/CTest/Curl/dict.c +++ b/Source/CTest/Curl/dict.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/dict.h b/Source/CTest/Curl/dict.h index 348403d..537e486 100644 --- a/Source/CTest/Curl/dict.h +++ b/Source/CTest/Curl/dict.h @@ -1,29 +1,30 @@ #ifndef __DICT_H #define __DICT_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ +#ifndef CURL_DISABLE_DICT CURLcode Curl_dict(struct connectdata *conn); CURLcode Curl_dict_done(struct connectdata *conn); - +#endif #endif diff --git a/Source/CTest/Curl/easy.c b/Source/CTest/Curl/easy.c index 45de7e8..b128180 100644 --- a/Source/CTest/Curl/easy.c +++ b/Source/CTest/Curl/easy.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -238,7 +238,7 @@ CURLcode curl_easy_perform(CURL *curl) data->hostcache = Curl_global_host_cache_get(); } else { - data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo); + data->hostcache = Curl_hash_alloc(7, Curl_freeaddrinfo); } } @@ -249,7 +249,7 @@ void curl_easy_cleanup(CURL *curl) { struct SessionHandle *data = (struct SessionHandle *)curl; if (!Curl_global_host_cache_use(data)) { - curl_hash_destroy(data->hostcache); + Curl_hash_destroy(data->hostcache); } Curl_close(data); } @@ -312,7 +312,8 @@ CURL *curl_easy_duphandle(CURL *incurl) /* If cookies are enabled in the parent handle, we enable them in the clone as well! */ outcurl->cookies = Curl_cookie_init(data->cookies->filename, - outcurl->cookies); + outcurl->cookies, + data->set.cookiesession); /* duplicate all values in 'change' */ if(data->change.url) { diff --git a/Source/CTest/Curl/escape.c b/Source/CTest/Curl/escape.c index 88f4359..0ec7ae5 100644 --- a/Source/CTest/Curl/escape.c +++ b/Source/CTest/Curl/escape.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* Escape and unescape URL encoding in strings. The functions return a new * allocated string or NULL if an error occurred. */ @@ -48,11 +48,9 @@ char *curl_escape(const char *string, int length) length = alloc-1; while(length--) { in = *string; - if(' ' == in) - ns[index++] = '+'; - else if(!(in >= 'a' && in <= 'z') && - !(in >= 'A' && in <= 'Z') && - !(in >= '0' && in <= '9')) { + if(!(in >= 'a' && in <= 'z') && + !(in >= 'A' && in <= 'Z') && + !(in >= '0' && in <= '9')) { /* encode it */ newlen += 2; /* the size grows with two, since this'll become a %XX */ if(newlen > alloc) { @@ -82,19 +80,10 @@ char *curl_unescape(const char *string, int length) unsigned char in; int index=0; unsigned int hex; - char querypart=FALSE; /* everything to the right of a '?' letter is - the "query part" where '+' should become ' '. - RFC 2316, section 3.10 */ while(--alloc > 0) { in = *string; - if(querypart && ('+' == in)) - in = ' '; - else if(!querypart && ('?' == in)) { - /* we have "walked in" to the query part */ - querypart=TRUE; - } - else if('%' == in) { + if('%' == in) { /* encoded part */ if(sscanf(string+1, "%02X", &hex)) { in = hex; @@ -111,6 +100,11 @@ char *curl_unescape(const char *string, int length) } +void curl_free(void *p) +{ + free(p); +} + /* * local variables: * eval: (load-file "../curl-mode.el") diff --git a/Source/CTest/Curl/escape.h b/Source/CTest/Curl/escape.h index cda6a65..5808207 100644 --- a/Source/CTest/Curl/escape.h +++ b/Source/CTest/Curl/escape.h @@ -1,28 +1,28 @@ #ifndef __ESCAPE_H #define __ESCAPE_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* Escape and unescape URL encoding in strings. The functions return a new * allocated string or NULL if an error occurred. */ diff --git a/Source/CTest/Curl/file.c b/Source/CTest/Curl/file.c index b2270aa..59b9bac 100644 --- a/Source/CTest/Curl/file.c +++ b/Source/CTest/Curl/file.c @@ -1,28 +1,29 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" +#ifndef CURL_DISABLE_FILE /* -- WIN32 approved -- */ #include <stdio.h> #include <string.h> @@ -140,7 +141,7 @@ CURLcode Curl_file(struct connectdata *conn) */ CURLcode res = CURLE_OK; struct stat statbuf; - ssize_t expected_size=-1; + double expected_size=-1; ssize_t nread; struct SessionHandle *data = conn->data; char *buf = data->state.buffer; @@ -155,9 +156,19 @@ CURLcode Curl_file(struct connectdata *conn) /*VMS?? -- This only works reliable for STREAMLF files */ if( -1 != fstat(fd, &statbuf)) { /* we could stat it, then read out the size */ - expected_size = statbuf.st_size; + expected_size = (double)statbuf.st_size; } + /* Added by Dolbneff A.V & Spiridonoff A.V */ + if (conn->resume_from <= expected_size) + expected_size -= conn->resume_from; + else + /* Is this error code suitable in such situation? */ + return CURLE_FTP_BAD_DOWNLOAD_RESUME; + + if (expected_size == 0) + return CURLE_OK; + /* The following is a shortcut implementation of file reading this is both more efficient than the former call to download() and it avoids problems with select() and recv() on file descriptors @@ -165,6 +176,10 @@ CURLcode Curl_file(struct connectdata *conn) if(expected_size != -1) Curl_pgrsSetDownloadSize(data, expected_size); + if(conn->resume_from) + /* Added by Dolbneff A.V & Spiridonoff A.V */ + lseek(fd, conn->resume_from, SEEK_SET); + while (res == CURLE_OK) { nread = read(fd, buf, BUFSIZE-1); @@ -204,3 +219,4 @@ CURLcode Curl_file(struct connectdata *conn) * vim600: fdm=marker * vim: et sw=2 ts=2 sts=2 tw=78 */ +#endif diff --git a/Source/CTest/Curl/file.h b/Source/CTest/Curl/file.h index 83ffa39..b11dcb7 100644 --- a/Source/CTest/Curl/file.h +++ b/Source/CTest/Curl/file.h @@ -1,28 +1,30 @@ #ifndef __FILE_H #define __FILE_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ +#ifndef CURL_DISABLE_FILE CURLcode Curl_file(struct connectdata *conn); CURLcode Curl_file_connect(struct connectdata *conn); #endif +#endif diff --git a/Source/CTest/Curl/formdata.c b/Source/CTest/Curl/formdata.c index e464559..b3503f3 100644 --- a/Source/CTest/Curl/formdata.c +++ b/Source/CTest/Curl/formdata.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* Debug the form generator stand-alone by compiling this source file with: @@ -109,6 +109,8 @@ Content-Disposition: form-data; name="FILECONTENT" #include "setup.h" +#ifndef CURL_DISABLE_HTTP + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -171,8 +173,8 @@ static void GetStr(char **string, static int FormParse(char *input, - struct HttpPost **httppost, - struct HttpPost **last_post) + struct curl_httppost **httppost, + struct curl_httppost **last_post) { /* nextarg MUST be a string in the format 'name=contents' and we'll build a linked list with the info */ @@ -186,8 +188,8 @@ int FormParse(char *input, char *prevtype = NULL; char *sep; char *sep2; - struct HttpPost *post; - struct HttpPost *subpost; /* a sub-node */ + struct curl_httppost *post; + struct curl_httppost *subpost; /* a sub-node */ unsigned int i; /* Preallocate contents to the length of input to make sure we don't @@ -296,9 +298,9 @@ int FormParse(char *input, /* For the first file name, we allocate and initiate the main list node */ - post = (struct HttpPost *)malloc(sizeof(struct HttpPost)); + post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost)); if(post) { - memset(post, 0, sizeof(struct HttpPost)); + memset(post, 0, sizeof(struct curl_httppost)); GetStr(&post->name, name); /* get the name */ GetStr(&post->contents, contp); /* get the contents */ post->contentslength = 0; @@ -320,9 +322,10 @@ int FormParse(char *input, else { /* we add a file name to the previously allocated node, known as 'post' now */ - subpost =(struct HttpPost *)malloc(sizeof(struct HttpPost)); + subpost =(struct curl_httppost *) + malloc(sizeof(struct curl_httppost)); if(subpost) { - memset(subpost, 0, sizeof(struct HttpPost)); + memset(subpost, 0, sizeof(struct curl_httppost)); GetStr(&subpost->name, name); /* get the name */ GetStr(&subpost->contents, contp); /* get the contents */ subpost->contentslength = 0; @@ -342,9 +345,9 @@ int FormParse(char *input, } while(sep && *sep); /* loop if there's another file name */ } else { - post = (struct HttpPost *)malloc(sizeof(struct HttpPost)); + post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost)); if(post) { - memset(post, 0, sizeof(struct HttpPost)); + memset(post, 0, sizeof(struct curl_httppost)); GetStr(&post->name, name); /* get the name */ if( contp[0]=='<' ) { GetStr(&post->contents, contp+1); /* get the contents */ @@ -378,8 +381,8 @@ int FormParse(char *input, } int curl_formparse(char *input, - struct HttpPost **httppost, - struct HttpPost **last_post) + struct curl_httppost **httppost, + struct curl_httppost **last_post) { return FormParse(input, httppost, last_post); } @@ -394,27 +397,37 @@ int curl_formparse(char *input, * Returns newly allocated HttpPost on success and NULL if malloc failed. * ***************************************************************************/ -static struct HttpPost * AddHttpPost(char * name, - long namelength, - char * value, - long contentslength, - char *contenttype, - long flags, - struct curl_slist* contentHeader, - struct HttpPost *parent_post, - struct HttpPost **httppost, - struct HttpPost **last_post) +static struct curl_httppost * +AddHttpPost(char * name, long namelength, + char * value, long contentslength, + + /* CMC: Added support for buffer uploads */ + char * buffer, long bufferlength, + + char *contenttype, + long flags, + struct curl_slist* contentHeader, + char *showfilename, + struct curl_httppost *parent_post, + struct curl_httppost **httppost, + struct curl_httppost **last_post) { - struct HttpPost *post; - post = (struct HttpPost *)malloc(sizeof(struct HttpPost)); + struct curl_httppost *post; + post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost)); if(post) { - memset(post, 0, sizeof(struct HttpPost)); + memset(post, 0, sizeof(struct curl_httppost)); post->name = name; post->namelength = name?(namelength?namelength:(long)strlen(name)):0; post->contents = value; post->contentslength = contentslength; + + /* CMC: Added support for buffer uploads */ + post->buffer = buffer; + post->bufferlength = bufferlength; + post->contenttype = contenttype; post->contentheader = contentHeader; + post->showfilename = showfilename; post->flags = flags; } else @@ -600,44 +613,31 @@ static int AllocAndCopy (char **buffer, int buffer_length) * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); * * Returns: - * FORMADD_OK on success - * FORMADD_MEMORY if the FormInfo allocation fails - * FORMADD_OPTION_TWICE if one option is given twice for one Form - * FORMADD_NULL if a null pointer was given for a char - * FORMADD_MEMORY if the allocation of a FormInfo struct failed - * FORMADD_UNKNOWN_OPTION if an unknown option was used - * FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error) - * FORMADD_MEMORY if a HttpPost struct cannot be allocated - * FORMADD_MEMORY if some allocation for string copying failed. - * FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error) + * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array * ***************************************************************************/ -typedef enum { - FORMADD_OK, /* first, no error */ - - FORMADD_MEMORY, - FORMADD_OPTION_TWICE, - FORMADD_NULL, - FORMADD_UNKNOWN_OPTION, - FORMADD_INCOMPLETE, - FORMADD_ILLEGAL_ARRAY, - - FORMADD_LAST /* last */ -} FORMcode; - static -FORMcode FormAdd(struct HttpPost **httppost, - struct HttpPost **last_post, - va_list params) +CURLFORMcode FormAdd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + va_list params) { FormInfo *first_form, *current_form, *form; - FORMcode return_value = FORMADD_OK; + CURLFORMcode return_value = CURL_FORMADD_OK; const char *prevtype = NULL; - struct HttpPost *post = NULL; + struct curl_httppost *post = NULL; CURLformoption option; struct curl_forms *forms = NULL; - const char *array_value; /* value read from an array */ + char *array_value=NULL; /* value read from an array */ /* This is a state variable, that if TRUE means that we're parsing an array that we got passed to us. If FALSE we're parsing the input @@ -653,7 +653,7 @@ FORMcode FormAdd(struct HttpPost **httppost, current_form = first_form; } else - return FORMADD_MEMORY; + return CURL_FORMADD_MEMORY; /* * Loop through all the options set. @@ -661,14 +661,14 @@ FORMcode FormAdd(struct HttpPost **httppost, while (1) { /* break if we have an error to report */ - if (return_value != FORMADD_OK) + if (return_value != CURL_FORMADD_OK) break; /* first see if we have more parts of the array param */ if ( array_state ) { /* get the upcoming option from the given array */ option = forms->option; - array_value = forms->value; + array_value = (char *)forms->value; forms++; /* advance this to next entry */ if (CURLFORM_END == option) { @@ -676,16 +676,6 @@ FORMcode FormAdd(struct HttpPost **httppost, array_state = FALSE; continue; } - else { - /* check that the option is OK in an array */ - - /* Daniel's note: do we really need to do this? */ - if ( (option <= CURLFORM_ARRAY_START) || - (option >= CURLFORM_ARRAY_END) ) { - return_value = FORMADD_ILLEGAL_ARRAY; - break; - } - } } else { /* This is not array-state, get next option */ @@ -696,11 +686,16 @@ FORMcode FormAdd(struct HttpPost **httppost, switch (option) { case CURLFORM_ARRAY: - forms = va_arg(params, struct curl_forms *); - if (forms) - array_state = TRUE; - else - return_value = FORMADD_NULL; + if(array_state) + /* we don't support an array from within an array */ + return_value = CURL_FORMADD_ILLEGAL_ARRAY; + else { + forms = va_arg(params, struct curl_forms *); + if (forms) + array_state = TRUE; + else + return_value = CURL_FORMADD_NULL; + } break; /* @@ -710,20 +705,22 @@ FORMcode FormAdd(struct HttpPost **httppost, current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ case CURLFORM_COPYNAME: if (current_form->name) - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; else { - char *name = va_arg(params, char *); + char *name = array_state? + array_value:va_arg(params, char *); if (name) current_form->name = name; /* store for the moment */ else - return_value = FORMADD_NULL; + return_value = CURL_FORMADD_NULL; } break; case CURLFORM_NAMELENGTH: if (current_form->namelength) - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; else - current_form->namelength = va_arg(params, long); + current_form->namelength = + array_state?(long)array_value:va_arg(params, long); break; /* @@ -733,117 +730,179 @@ FORMcode FormAdd(struct HttpPost **httppost, current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */ case CURLFORM_COPYCONTENTS: if (current_form->value) - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; else { - char *value = va_arg(params, char *); + char *value = + array_state?array_value:va_arg(params, char *); if (value) current_form->value = value; /* store for the moment */ else - return_value = FORMADD_NULL; + return_value = CURL_FORMADD_NULL; } break; case CURLFORM_CONTENTSLENGTH: if (current_form->contentslength) - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; else - current_form->contentslength = va_arg(params, long); + current_form->contentslength = + array_state?(long)array_value:va_arg(params, long); break; /* Get contents from a given file name */ case CURLFORM_FILECONTENT: if (current_form->flags != 0) - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; else { - char *filename = va_arg(params, char *); + char *filename = array_state? + array_value:va_arg(params, char *); if (filename) { current_form->value = strdup(filename); current_form->flags |= HTTPPOST_READFILE; } else - return_value = FORMADD_NULL; + return_value = CURL_FORMADD_NULL; } break; /* We upload a file */ case CURLFORM_FILE: { - const char *filename = NULL; - if (array_state) - filename = array_value; - else - filename = va_arg(params, const char *); + char *filename = array_state?array_value: + va_arg(params, char *); + if (current_form->value) { if (current_form->flags & HTTPPOST_FILENAME) { if (filename) { if (!(current_form = AddFormInfo(strdup(filename), NULL, current_form))) - return_value = FORMADD_MEMORY; + return_value = CURL_FORMADD_MEMORY; } else - return_value = FORMADD_NULL; + return_value = CURL_FORMADD_NULL; } else - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; } else { if (filename) current_form->value = strdup(filename); else - return_value = FORMADD_NULL; + return_value = CURL_FORMADD_NULL; current_form->flags |= HTTPPOST_FILENAME; } break; } - case CURLFORM_CONTENTTYPE: + + /* CMC: Added support for buffer uploads */ + case CURLFORM_BUFFER: { - const char *contenttype = NULL; - if (array_state) - contenttype = array_value; + char *filename = array_state?array_value: + va_arg(params, char *); + + if (current_form->value) { + if (current_form->flags & HTTPPOST_BUFFER) { + if (filename) { + if (!(current_form = AddFormInfo(strdup(filename), + NULL, current_form))) + return_value = CURL_FORMADD_MEMORY; + } + else + return_value = CURL_FORMADD_NULL; + } + else + return_value = CURL_FORMADD_OPTION_TWICE; + } + else { + if (filename) + current_form->value = strdup(filename); + else + return_value = CURL_FORMADD_NULL; + current_form->flags |= HTTPPOST_BUFFER; + } + break; + } + + /* CMC: Added support for buffer uploads */ + case CURLFORM_BUFFERPTR: + current_form->flags |= HTTPPOST_PTRBUFFER; + if (current_form->buffer) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *buffer = + array_state?array_value:va_arg(params, char *); + if (buffer) + current_form->buffer = buffer; /* store for the moment */ else - contenttype = va_arg(params, const char *); + return_value = CURL_FORMADD_NULL; + } + break; + + /* CMC: Added support for buffer uploads */ + case CURLFORM_BUFFERLENGTH: + if (current_form->bufferlength) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->bufferlength = + array_state?(long)array_value:va_arg(params, long); + break; + + case CURLFORM_CONTENTTYPE: + { + char *contenttype = + array_state?array_value:va_arg(params, char *); if (current_form->contenttype) { if (current_form->flags & HTTPPOST_FILENAME) { if (contenttype) { if (!(current_form = AddFormInfo(NULL, strdup(contenttype), current_form))) - return_value = FORMADD_MEMORY; + return_value = CURL_FORMADD_MEMORY; } else - return_value = FORMADD_NULL; + return_value = CURL_FORMADD_NULL; } else - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; } else { if (contenttype) current_form->contenttype = strdup(contenttype); else - return_value = FORMADD_NULL; + return_value = CURL_FORMADD_NULL; } break; } case CURLFORM_CONTENTHEADER: { - struct curl_slist* list = NULL; - if( array_state ) - list = (struct curl_slist*)array_value; - else - list = va_arg(params,struct curl_slist*); + /* this "cast increases required alignment of target type" but + we consider it OK anyway */ + struct curl_slist* list = array_state? + (struct curl_slist*)array_value: + va_arg(params, struct curl_slist*); if( current_form->contentheader ) - return_value = FORMADD_OPTION_TWICE; + return_value = CURL_FORMADD_OPTION_TWICE; else current_form->contentheader = list; break; } + case CURLFORM_FILENAME: + { + char *filename = array_state?array_value: + va_arg(params, char *); + if( current_form->showfilename ) + return_value = CURL_FORMADD_OPTION_TWICE; + else + current_form->showfilename = strdup(filename); + break; + } default: - return_value = FORMADD_UNKNOWN_OPTION; + return_value = CURL_FORMADD_UNKNOWN_OPTION; } } - if(FORMADD_OK == return_value) { + if(CURL_FORMADD_OK == return_value) { /* go through the list, check for copleteness and if everything is * alright add the HttpPost item otherwise set return_value accordingly */ @@ -856,14 +915,21 @@ FORMcode FormAdd(struct HttpPost **httppost, (form->flags & HTTPPOST_FILENAME) ) || ( (form->flags & HTTPPOST_FILENAME) && (form->flags & HTTPPOST_PTRCONTENTS) ) || + + /* CMC: Added support for buffer uploads */ + ( (!form->buffer) && + (form->flags & HTTPPOST_BUFFER) && + (form->flags & HTTPPOST_PTRBUFFER) ) || + ( (form->flags & HTTPPOST_READFILE) && (form->flags & HTTPPOST_PTRCONTENTS) ) ) { - return_value = FORMADD_INCOMPLETE; + return_value = CURL_FORMADD_INCOMPLETE; break; } else { - if ( (form->flags & HTTPPOST_FILENAME) && + if ( ((form->flags & HTTPPOST_FILENAME) || + (form->flags & HTTPPOST_BUFFER)) && !form->contenttype ) { /* our contenttype is missing */ form->contenttype @@ -873,28 +939,36 @@ FORMcode FormAdd(struct HttpPost **httppost, (form == first_form) ) { /* copy name (without strdup; possibly contains null characters) */ if (AllocAndCopy(&form->name, form->namelength)) { - return_value = FORMADD_MEMORY; + return_value = CURL_FORMADD_MEMORY; break; } } if ( !(form->flags & HTTPPOST_FILENAME) && !(form->flags & HTTPPOST_READFILE) && - !(form->flags & HTTPPOST_PTRCONTENTS) ) { + !(form->flags & HTTPPOST_PTRCONTENTS) && + + /* CMC: Added support for buffer uploads */ + !(form->flags & HTTPPOST_PTRBUFFER) ) { + /* copy value (without strdup; possibly contains null characters) */ if (AllocAndCopy(&form->value, form->contentslength)) { - return_value = FORMADD_MEMORY; + return_value = CURL_FORMADD_MEMORY; break; } } post = AddHttpPost(form->name, form->namelength, form->value, form->contentslength, + + /* CMC: Added support for buffer uploads */ + form->buffer, form->bufferlength, + form->contenttype, form->flags, - form->contentheader, + form->contentheader, form->showfilename, post, httppost, last_post); if(!post) - return_value = FORMADD_MEMORY; + return_value = CURL_FORMADD_MEMORY; if (form->contenttype) prevtype = form->contenttype; @@ -915,12 +989,12 @@ FORMcode FormAdd(struct HttpPost **httppost, return return_value; } -int curl_formadd(struct HttpPost **httppost, - struct HttpPost **last_post, +CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, ...) { va_list arg; - int result; + CURLFORMcode result; va_start(arg, last_post); result = FormAdd(httppost, last_post, arg); va_end(arg); @@ -975,8 +1049,8 @@ char *Curl_FormBoundary(void) the same form won't be identical */ int i; - static char table64[]= - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + static char table62[]= + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; retstring = (char *)malloc(BOUNDARY_LENGTH); @@ -988,7 +1062,7 @@ char *Curl_FormBoundary(void) strcpy(retstring, "curl"); /* bonus commercials 8*) */ for(i=4; i<(BOUNDARY_LENGTH-1); i++) { - retstring[i] = table64[rand()%64]; + retstring[i] = table62[rand()%62]; } retstring[BOUNDARY_LENGTH-1]=0; /* zero terminate */ @@ -1009,9 +1083,9 @@ void Curl_formclean(struct FormData *form) } /* external function to free up a whole form post chain */ -void curl_formfree(struct HttpPost *form) +void curl_formfree(struct curl_httppost *form) { - struct HttpPost *next; + struct curl_httppost *next; if(!form) /* no form to free, just get out of this */ @@ -1030,27 +1104,31 @@ void curl_formfree(struct HttpPost *form) free(form->contents); /* free the contents */ if(form->contenttype) free(form->contenttype); /* free the content type */ + if(form->showfilename) + free(form->showfilename); /* free the faked file name */ free(form); /* free the struct */ } while((form=next)); /* continue */ } -struct FormData *Curl_getFormData(struct HttpPost *post, - int *sizep) +CURLcode Curl_getFormData(struct FormData **finalform, + struct curl_httppost *post, + int *sizep) { struct FormData *form = NULL; struct FormData *firstform; - - struct HttpPost *file; + struct curl_httppost *file; + CURLcode result = CURLE_OK; int size =0; char *boundary; char *fileboundary=NULL; struct curl_slist* curList; + *finalform=NULL; /* default form is empty */ if(!post) - return NULL; /* no input => no output! */ + return result; /* no input => no output! */ boundary = Curl_FormBoundary(); @@ -1093,16 +1171,29 @@ struct FormData *Curl_getFormData(struct HttpPost *post, file = post; do { + + /* If 'showfilename' is set, that is a faked name passed on to us + to use to in the formpost. If that is not set, the actually used + local file name should be added. */ + if(post->more) { /* if multiple-file */ size += AddFormDataf(&form, - "\r\n--%s\r\nContent-Disposition: attachment; filename=\"%s\"", - fileboundary, file->contents); + "\r\n--%s\r\nContent-Disposition: " + "attachment; filename=\"%s\"", + fileboundary, + (file->showfilename?file->showfilename: + file->contents)); } - else if(post->flags & HTTPPOST_FILENAME) { + else if((post->flags & HTTPPOST_FILENAME) || + + /* CMC: Added support for buffer uploads */ + (post->flags & HTTPPOST_BUFFER)) { + size += AddFormDataf(&form, "; filename=\"%s\"", - post->contents); + (post->showfilename?post->showfilename: + post->contents)); } if(file->contenttype) { @@ -1127,7 +1218,7 @@ struct FormData *Curl_getFormData(struct HttpPost *post, */ if(file->contenttype && - !strnequal("text/", file->contenttype, 5)) { + !checkprefix("text/", file->contenttype)) { /* this is not a text content, mention our binary encoding */ size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0); } @@ -1144,24 +1235,34 @@ struct FormData *Curl_getFormData(struct HttpPost *post, fileread = strequal("-", file->contents)?stdin: /* binary read for win32 crap */ -/*VMS??*/ fopen(file->contents, "rb"); /* ONLY ALLOWS FOR STREAM FILES ON VMS */ -/*VMS?? Stream files are OK, as are FIXED & VAR files WITHOUT implied CC */ -/*VMS?? For implied CC, every record needs to have a \n appended & 1 added to SIZE */ + /*VMS??*/ fopen(file->contents, "rb"); /* ONLY ALLOWS FOR STREAM FILES ON VMS */ + /*VMS?? Stream files are OK, as are FIXED & VAR files WITHOUT implied CC */ + /*VMS?? For implied CC, every record needs to have a \n appended & 1 added to SIZE */ if(fileread) { - while((nread = fread(buffer, 1, 1024, fileread))) { - size += AddFormData(&form, - buffer, - nread); - } + while((nread = fread(buffer, 1, 1024, fileread))) + size += AddFormData(&form, buffer, nread); + if(fileread != stdin) fclose(fileread); } else { +#if 0 /* File wasn't found, add a nothing field! */ size += AddFormData(&form, "", 0); +#endif + Curl_formclean(firstform); + free(boundary); + *finalform = NULL; + return CURLE_READ_ERROR; } + + /* CMC: Added support for buffer uploads */ + } else if (post->flags & HTTPPOST_BUFFER) { + /* include contents of buffer */ + size += AddFormData(&form, post->buffer, post->bufferlength); } - else { + + else { /* include the contents we got */ size += AddFormData(&form, post->contents, post->contentslength); } @@ -1187,7 +1288,9 @@ struct FormData *Curl_getFormData(struct HttpPost *post, free(boundary); - return firstform; + *finalform=firstform; + + return result; } int Curl_FormInit(struct Form *form, struct FormData *formdata ) @@ -1294,8 +1397,8 @@ int Curl_FormReadOneLine(char *buffer, #ifdef _FORM_DEBUG int FormAddTest(const char * errormsg, - struct HttpPost **httppost, - struct HttpPost **last_post, + struct curl_httppost **httppost, + struct curl_httppost **last_post, ...) { int result; @@ -1341,8 +1444,8 @@ int main() int size; int nread; char buffer[4096]; - struct HttpPost *httppost=NULL; - struct HttpPost *last_post=NULL; + struct curl_httppost *httppost=NULL; + struct curl_httppost *last_post=NULL; struct curl_forms forms[4]; struct FormData *form; @@ -1451,9 +1554,9 @@ int main(int argc, char **argv) #endif int i; char *nextarg; - struct HttpPost *httppost=NULL; - struct HttpPost *last_post=NULL; - struct HttpPost *post; + struct curl_httppost *httppost=NULL; + struct curl_httppost *last_post=NULL; + struct curl_httppost *post; int size; int nread; char buffer[4096]; @@ -1492,6 +1595,8 @@ int main(int argc, char **argv) #endif +#endif /* CURL_DISABLE_HTTP */ + /* * local variables: * eval: (load-file "../curl-mode.el") diff --git a/Source/CTest/Curl/formdata.h b/Source/CTest/Curl/formdata.h index 817c0d6..d1cc674 100644 --- a/Source/CTest/Curl/formdata.h +++ b/Source/CTest/Curl/formdata.h @@ -1,28 +1,28 @@ #ifndef __FORMDATA_H #define __FORMDATA_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* plain and simple linked list with lines to send */ struct FormData { struct FormData *next; @@ -44,14 +44,23 @@ typedef struct FormInfo { long contentslength; char *contenttype; long flags; + + /* CMC: Added support for buffer uploads */ + char *buffer; /* pointer to existing buffer used for file upload */ + long bufferlength; + + char *showfilename; /* The file name to show. If not set, the actual + file name will be used */ struct curl_slist* contentheader; struct FormInfo *more; } FormInfo; int Curl_FormInit(struct Form *form, struct FormData *formdata ); -struct FormData *Curl_getFormData(struct HttpPost *post, - int *size); +CURLcode +Curl_getFormData(struct FormData **, + struct HttpPost *post, + int *size); /* fread() emulation */ int Curl_FormReader(char *buffer, diff --git a/Source/CTest/Curl/ftp.c b/Source/CTest/Curl/ftp.c index 127971b..ac5f841 100644 --- a/Source/CTest/Curl/ftp.c +++ b/Source/CTest/Curl/ftp.c @@ -1,28 +1,29 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" +#ifndef CURL_DISABLE_FTP #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -210,16 +211,6 @@ int Curl_GetFTPResponse(char *buf, if (ftpcode) *ftpcode = 0; /* 0 for errors */ - if(data->set.timeout) { - /* if timeout is requested, find out how much remaining time we have */ - timeout = data->set.timeout - /* timeout time */ - Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ - if(timeout <=0 ) { - failf(data, "Transfer aborted due to timeout"); - return -SELECT_TIMEOUT; /* already too little time */ - } - } - FD_ZERO (&readfd); /* clear it */ FD_SET (sockfd, &readfd); /* read socket */ @@ -235,11 +226,22 @@ int Curl_GetFTPResponse(char *buf, keepon=TRUE; while((nread<BUFSIZE) && (keepon && !error)) { - readfd = rkeepfd; /* set every lap */ - interval.tv_sec = timeout; - interval.tv_usec = 0; + /* check and reset timeout value every lap */ + if(data->set.timeout) { + /* if timeout is requested, find out how much remaining time we have */ + timeout = data->set.timeout - /* timeout time */ + Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */ + if(timeout <=0 ) { + failf(data, "Transfer aborted due to timeout"); + return -SELECT_TIMEOUT; /* already too little time */ + } + } + + if(!ftp->cache) { + readfd = rkeepfd; /* set every lap */ + interval.tv_sec = timeout; + interval.tv_usec = 0; - if(!ftp->cache) switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) { case -1: /* select() error, stop reading */ error = SELECT_ERROR; @@ -253,6 +255,7 @@ int Curl_GetFTPResponse(char *buf, error = SELECT_OK; break; } + } if(SELECT_OK == error) { /* * This code previously didn't use the kerberos sec_read() code @@ -301,11 +304,8 @@ int Curl_GetFTPResponse(char *buf, CURLcode result; /* output debug output if that is requested */ - if(data->set.verbose) { - fputs("< ", data->set.err); - fwrite(line_start, perline, 1, data->set.err); - /* no need to output LF here, it is part of the data */ - } + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, line_start, perline); /* * We pass all response-lines to the callback function registered @@ -387,33 +387,10 @@ int Curl_GetFTPResponse(char *buf, return nread; /* total amount of bytes read */ } -#ifndef ENABLE_IPV6 /* - * This function is only used by code that works on IPv4. When we add proper - * support for that functionality with IPv6, this function can go in again. + * Curl_ftp_connect() should do everything that is to be considered a part of + * the connection phase. */ -/* -- who are we? -- */ -static char *getmyhost(char *buf, int buf_size) -{ -#if defined(HAVE_GETHOSTNAME) - gethostname(buf, buf_size); -#elif defined(HAVE_UNAME) - struct utsname ugnm; - strncpy(buf, uname(&ugnm) < 0 ? "localhost" : ugnm.nodename, buf_size - 1); - buf[buf_size - 1] = '\0'; -#else - /* We have no means of finding the local host name! */ - strncpy(buf, "localhost", buf_size); - buf[buf_size - 1] = '\0'; -#endif - return buf; -} - -#endif /* ipv4-only function */ - - -/* ftp_connect() should do everything that is to be considered a part - of the connection phase. */ CURLcode Curl_ftp_connect(struct connectdata *conn) { /* this is FTP and no proxy */ @@ -622,8 +599,10 @@ CURLcode Curl_ftp_done(struct connectdata *conn) CURLcode result=CURLE_OK; if(data->set.upload) { - if((-1 != data->set.infilesize) && (data->set.infilesize != *ftp->bytecountp)) { - failf(data, "Wrote only partial file (%d out of %d bytes)", + if((-1 != data->set.infilesize) && + (data->set.infilesize != *ftp->bytecountp) && + !data->set.crlf) { + failf(data, "Uploaded unaligned file size (%d out of %d bytes)", *ftp->bytecountp, data->set.infilesize); return CURLE_PARTIAL_FILE; } @@ -634,9 +613,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn) failf(data, "Received only partial file: %d bytes", *ftp->bytecountp); return CURLE_PARTIAL_FILE; } - else if(!conn->bits.resume_done && - !data->set.no_body && - (0 == *ftp->bytecountp)) { + else if(!ftp->dont_check && + !*ftp->bytecountp && + (conn->size>0)) { /* We consider this an error, but there's no true FTP error received why we need to continue to "read out" the server response too. We don't want to leave a "waiting" server reply if we'll get told @@ -653,21 +632,25 @@ CURLcode Curl_ftp_done(struct connectdata *conn) sclose(conn->secondarysocket); conn->secondarysocket = -1; - if(!data->set.no_body && !conn->bits.resume_done) { - /* now let's see what the server says about the transfer we - just performed: */ + if(!ftp->no_transfer) { + /* now let's see what the server says about the transfer we just + performed: */ nread = Curl_GetFTPResponse(buf, conn, &ftpcode); if(nread < 0) return CURLE_OPERATION_TIMEOUTED; - /* 226 Transfer complete, 250 Requested file action okay, completed. */ - if((ftpcode != 226) && (ftpcode != 250)) { - failf(data, "server did not report OK, got %d", ftpcode); - return CURLE_FTP_WRITE_ERROR; + if(!ftp->dont_check) { + /* 226 Transfer complete, 250 Requested file action okay, completed. */ + if((ftpcode != 226) && (ftpcode != 250)) { + failf(data, "server did not report OK, got %d", ftpcode); + return CURLE_FTP_WRITE_ERROR; + } } } - conn->bits.resume_done = FALSE; /* clean this for next connection */ + /* clear these for next connection */ + ftp->no_transfer = FALSE; + ftp->dont_check = FALSE; /* Send any post-transfer QUOTE strings? */ if(!result && data->set.postquote) @@ -728,8 +711,7 @@ CURLcode ftp_cwd(struct connectdata *conn, char *path) CURLcode result; FTPSENDF(conn, "CWD %s", path); - nread = Curl_GetFTPResponse( - conn->data->state.buffer, conn, &ftpcode); + nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode); if (nread < 0) return CURLE_OPERATION_TIMEOUTED; @@ -898,15 +880,19 @@ ftp_pasv_verbose(struct connectdata *conn, /* Bjorn Reese (November 28 2001): The Tru64 man page on gethostbyaddr_r() says that the hostent struct must be filled with zeroes before the call to - gethostbyaddr_r(). */ + gethostbyaddr_r(). + + ... as must be struct hostent_data Craig Markwardt 19 Sep 2002. */ - memset(hostent_buf, 0, sizeof(struct hostent)); + memset(hostent_buf, 0, sizeof(struct hostent)+sizeof(struct hostent_data)); if(gethostbyaddr_r((char *) &address, sizeof(address), AF_INET, (struct hostent *)hostent_buf, - hostent_buf + sizeof(*answer))) + (struct hostent_data *)(hostent_buf + sizeof(*answer)))) answer=NULL; + else + answer=(struct hostent *)hostent_buf; # endif # ifdef HAVE_GETHOSTBYADDR_R_7 @@ -914,7 +900,7 @@ ftp_pasv_verbose(struct connectdata *conn, answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET, (struct hostent *)bigbuf, hostent_buf + sizeof(*answer), - sizeof(hostent_buf) - sizeof(*answer), + sizeof(bigbuf) - sizeof(*answer), &h_errnop); # endif # ifdef HAVE_GETHOSTBYADDR_R_8 @@ -922,7 +908,7 @@ ftp_pasv_verbose(struct connectdata *conn, if(gethostbyaddr_r((char *) &address, sizeof(address), AF_INET, (struct hostent *)hostent_buf, hostent_buf + sizeof(*answer), - sizeof(hostent_buf) - sizeof(*answer), + sizeof(bigbuf) - sizeof(*answer), &answer, &h_errnop)) answer=NULL; /* error */ @@ -1013,7 +999,6 @@ CURLcode ftp_use_port(struct connectdata *conn) #endif unsigned char *ap; unsigned char *pp; - int alen, plen; char portmsgbuf[4096], tmp[4096]; const char *mode[] = { "EPRT", "LPRT", "PORT", NULL }; @@ -1064,18 +1049,19 @@ CURLcode ftp_use_port(struct connectdata *conn) } freeaddrinfo(res); if (portsock < 0) { - failf(data, strerror(errno)); + failf(data, "%s", strerror(errno)); return CURLE_FTP_PORT_FAILED; } sslen = sizeof(ss); if (getsockname(portsock, sa, &sslen) < 0) { - failf(data, strerror(errno)); + failf(data, "%s", strerror(errno)); return CURLE_FTP_PORT_FAILED; } for (modep = (char **)mode; modep && *modep; modep++) { int lprtaf, eprtaf; + int alen=0, plen=0; switch (sa->sa_family) { case AF_INET: @@ -1197,30 +1183,42 @@ CURLcode ftp_use_port(struct connectdata *conn) * */ struct sockaddr_in sa; - struct hostent *h=NULL; - char *hostdataptr=NULL; + struct Curl_dns_entry *h=NULL; unsigned short porttouse; char myhost[256] = ""; + bool sa_filled_in = FALSE; if(data->set.ftpport) { if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) { - h = Curl_resolv(data, myhost, 0, &hostdataptr); + h = Curl_resolv(data, myhost, 0); } else { int len = strlen(data->set.ftpport); if(len>1) - h = Curl_resolv(data, data->set.ftpport, 0, &hostdataptr); + h = Curl_resolv(data, data->set.ftpport, 0); if(h) strcpy(myhost, data->set.ftpport); /* buffer overflow risk */ } } if(! *myhost) { - char *tmp_host = getmyhost(myhost, sizeof(myhost)); - h=Curl_resolv(data, tmp_host, 0, &hostdataptr); + /* pick a suitable default here */ + + socklen_t sslen; + + sslen = sizeof(sa); + if (getsockname(conn->firstsocket, (struct sockaddr *)&sa, &sslen) < 0) { + failf(data, "getsockname() failed"); + return CURLE_FTP_PORT_FAILED; + } + + sa_filled_in = TRUE; /* the sa struct is filled in */ } - infof(data, "We connect from %s\n", myhost); - - if ( h ) { + + if(h) + /* when we return from here, we can forget about this */ + Curl_resolv_unlock(h); + + if ( h || sa_filled_in) { if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) { int size; @@ -1229,12 +1227,15 @@ CURLcode ftp_use_port(struct connectdata *conn) we fail before the true secondary stuff is made */ conn->secondarysocket = portsock; - memset((char *)&sa, 0, sizeof(sa)); - memcpy((char *)&sa.sin_addr, - h->h_addr, - h->h_length); - sa.sin_family = AF_INET; - sa.sin_addr.s_addr = INADDR_ANY; + if(!sa_filled_in) { + memset((char *)&sa, 0, sizeof(sa)); + memcpy((char *)&sa.sin_addr, + h->addr->h_addr, + h->addr->h_length); + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = INADDR_ANY; + } + sa.sin_port = 0; size = sizeof(sa); @@ -1252,19 +1253,16 @@ CURLcode ftp_use_port(struct connectdata *conn) if ( listen(portsock, 1) < 0 ) { failf(data, "listen(2) failed on socket"); - free(hostdataptr); return CURLE_FTP_PORT_FAILED; } } else { failf(data, "bind(2) failed on socket"); - free(hostdataptr); return CURLE_FTP_PORT_FAILED; } } else { failf(data, "socket(2) failed (%s)"); - free(hostdataptr); return CURLE_FTP_PORT_FAILED; } } @@ -1278,7 +1276,10 @@ CURLcode ftp_use_port(struct connectdata *conn) #endif struct in_addr in; unsigned short ip[5]; - (void) memcpy(&in.s_addr, *h->h_addr_list, sizeof (in.s_addr)); + (void) memcpy(&in.s_addr, + h?*h->addr->h_addr_list:(char *)&sa.sin_addr.s_addr, + sizeof (in.s_addr)); + #ifdef HAVE_INET_NTOA_R /* ignore the return code from inet_ntoa_r() as it is int or char * depending on system */ @@ -1289,6 +1290,9 @@ CURLcode ftp_use_port(struct connectdata *conn) sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu", &ip[0], &ip[1], &ip[2], &ip[3]); #endif + infof(data, "Telling server to connect to %d.%d.%d.%d:%d\n", + ip[0], ip[1], ip[2], ip[3], porttouse); + result=Curl_ftpsendf(conn, "PORT %d,%d,%d,%d,%d,%d", ip[0], ip[1], ip[2], ip[3], porttouse >> 8, @@ -1320,14 +1324,15 @@ CURLcode ftp_use_port(struct connectdata *conn) */ static -CURLcode ftp_use_pasv(struct connectdata *conn) +CURLcode ftp_use_pasv(struct connectdata *conn, + bool *connected) { struct SessionHandle *data = conn->data; ssize_t nread; char *buf = data->state.buffer; /* this is our buffer */ int ftpcode; /* receive FTP response codes in this */ CURLcode result; - Curl_addrinfo *addr=NULL; + struct Curl_dns_entry *addr=NULL; Curl_ipconnect *conninfo; /* @@ -1358,8 +1363,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn) #endif int modeoff; unsigned short connectport; /* the local port connect() should use! */ - unsigned short newport; /* remote port, not necessary the local one */ - char *hostdataptr=NULL; + unsigned short newport=0; /* remote port, not necessary the local one */ /* newhost must be able to hold a full IP-style address in ASCII, which in the IPv6 case means 5*8-1 = 39 letters */ @@ -1368,7 +1372,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn) for (modeoff = (data->set.ftp_use_epsv?0:1); mode[modeoff]; modeoff++) { - result = Curl_ftpsendf(conn, mode[modeoff]); + result = Curl_ftpsendf(conn, "%s", mode[modeoff]); if(result) return result; nread = Curl_GetFTPResponse(buf, conn, &ftpcode); @@ -1449,18 +1453,21 @@ CURLcode ftp_use_pasv(struct connectdata *conn) if(data->change.proxy) { /* * This is a tunnel through a http proxy and we need to connect to the - * proxy again here. We already have the name info for it since the - * previous lookup. + * proxy again here. + * + * We don't want to rely on a former host lookup that might've expired + * now, instead we remake the lookup here and now! */ - addr = conn->hostaddr; + addr = Curl_resolv(data, conn->proxyhost, conn->port); connectport = - (unsigned short)conn->port; /* we connect to the proxy's port */ + (unsigned short)conn->port; /* we connect to the proxy's port */ + } else { /* normal, direct, ftp connection */ - addr = Curl_resolv(data, newhostp, newport, &hostdataptr); + addr = Curl_resolv(data, newhostp, newport); if(!addr) { - failf(data, "Can't resolve new host %s", newhost); + failf(data, "Can't resolve new host %s:%d", newhostp, newport); return CURLE_FTP_CANT_GET_HOST; } connectport = newport; /* we connect to the remote port */ @@ -1470,12 +1477,21 @@ CURLcode ftp_use_pasv(struct connectdata *conn) addr, connectport, &conn->secondarysocket, - &conninfo); + &conninfo, + connected); + + Curl_resolv_unlock(addr); /* we're done using this address */ + + /* + * When this is used from the multi interface, this might've returned with + * the 'connected' set to FALSE and thus we are now awaiting a non-blocking + * connect to connect and we should not be "hanging" here waiting. + */ if((CURLE_OK == result) && data->set.verbose) /* this just dumps information about this second connection */ - ftp_pasv_verbose(conn, conninfo, newhost, connectport); + ftp_pasv_verbose(conn, conninfo, newhostp, connectport); if(CURLE_OK != result) return result; @@ -1483,7 +1499,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn) if (data->set.tunnel_thru_httpproxy) { /* We want "seamless" FTP operations through HTTP proxy tunnel */ result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket, - newhost, newport); + newhostp, newport); if(CURLE_OK != result) return result; } @@ -1491,125 +1507,24 @@ CURLcode ftp_use_pasv(struct connectdata *conn) return CURLE_OK; } -/*********************************************************************** - * - * ftp_perform() +/* + * Curl_ftp_nextconnect() * - * This is the actual DO function for FTP. Get a file/directory according to - * the options previously setup. + * This function shall be called when the second FTP connection has been + * established and is confirmed connected. */ -static -CURLcode ftp_perform(struct connectdata *conn) +CURLcode Curl_ftp_nextconnect(struct connectdata *conn) { - /* this is FTP and no proxy */ - ssize_t nread; - CURLcode result; struct SessionHandle *data=conn->data; char *buf = data->state.buffer; /* this is our buffer */ + CURLcode result; + ssize_t nread; + int ftpcode; /* for ftp status */ /* the ftp struct is already inited in ftp_connect() */ struct FTP *ftp = conn->proto.ftp; - long *bytecountp = ftp->bytecountp; - int ftpcode; /* for ftp status */ - - /* Send any QUOTE strings? */ - if(data->set.quote) { - if ((result = ftp_sendquote(conn, data->set.quote)) != CURLE_OK) - return result; - } - - /* This is a re-used connection. Since we change directory to where the - transfer is taking place, we must now get back to the original dir - where we ended up after login: */ - if (conn->bits.reuse) { - if ((result = ftp_cwd(conn, ftp->entrypath)) != CURLE_OK) - return result; - } - - /* change directory first! */ - if(ftp->dir && ftp->dir[0]) { - if ((result = ftp_cwd(conn, ftp->dir)) != CURLE_OK) - return result; - } - - /* Requested time of file? */ - if(data->set.get_filetime && ftp->file) { - result = ftp_getfiletime(conn, ftp->file); - if(result) - return result; - } - - /* If we have selected NOBODY and HEADER, it means that we only want file - information. Which in FTP can't be much more than the file size and - date. */ - if(data->set.no_body && data->set.include_header) { - /* The SIZE command is _not_ RFC 959 specified, and therefor many servers - may not support it! It is however the only way we have to get a file's - size! */ - ssize_t filesize; - - /* Some servers return different sizes for different modes, and thus we - must set the proper type before we check the size */ - result = ftp_transfertype(conn, data->set.ftp_ascii); - if(result) - return result; - - /* failing to get size is not a serious error */ - result = ftp_getsize(conn, ftp->file, &filesize); - - if(CURLE_OK == result) { - sprintf(buf, "Content-Length: %d\r\n", filesize); - result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); - if(result) - return result; - } - - /* If we asked for a time of the file and we actually got one as - well, we "emulate" a HTTP-style header in our output. */ - -#ifdef HAVE_STRFTIME - if(data->set.get_filetime && data->info.filetime) { - struct tm *tm; -#ifdef HAVE_LOCALTIME_R - struct tm buffer; - tm = (struct tm *)localtime_r(&data->info.filetime, &buffer); -#else - tm = localtime((unsigned long *)&data->info.filetime); -#endif - /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ - strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S %Z\r\n", - tm); - result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); - if(result) - return result; - } -#endif - - return CURLE_OK; - } - - if(data->set.no_body) - /* don't transfer the data */ - ; - /* Get us a second connection up and connected */ - else if(data->set.ftp_use_port) { - /* We have chosen to use the PORT command */ - result = ftp_use_port(conn); - if(CURLE_OK == result) - /* we have the data connection ready */ - infof(data, "Connected the data stream with PORT!\n"); - } - else { - /* We have chosen (this is default) to use the PASV command */ - result = ftp_use_pasv(conn); - if(CURLE_OK == result) - infof(data, "Connected the data stream with PASV!\n"); - } - - if(result) - return result; if(data->set.upload) { @@ -1688,10 +1603,9 @@ CURLcode ftp_perform(struct connectdata *conn) /* no data to transfer */ result=Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL); - /* Set resume done so that we won't get any error in - * Curl_ftp_done() because we didn't transfer the amount of bytes - * that the local file file obviously is */ - conn->bits.resume_done = TRUE; + /* Set no_transfer so that we won't get any error in + * Curl_ftp_done() because we didn't transfer anything! */ + ftp->no_transfer = TRUE; return CURLE_OK; } @@ -1780,6 +1694,7 @@ CURLcode ftp_perform(struct connectdata *conn) } infof(data, "range-download from %d to %d, totally %d bytes\n", from, to, totalsize); + ftp->dont_check = TRUE; /* dont check for successful transfer */ } if((data->set.ftp_list_only) || !ftp->file) { @@ -1872,11 +1787,9 @@ CURLcode ftp_perform(struct connectdata *conn) result=Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL); infof(data, "File already completely downloaded\n"); - /* Set resume done so that we won't get any error in Curl_ftp_done() - * because we didn't transfer the amount of bytes that the remote - * file obviously is */ - conn->bits.resume_done = TRUE; - + /* Set no_transfer so that we won't get any error in Curl_ftp_done() + * because we didn't transfer the any file */ + ftp->no_transfer = TRUE; return CURLE_OK; } @@ -1990,6 +1903,128 @@ CURLcode ftp_perform(struct connectdata *conn) /*********************************************************************** * + * ftp_perform() + * + * This is the actual DO function for FTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode ftp_perform(struct connectdata *conn, + bool *connected) /* for the TCP connect status after + PASV / PORT */ +{ + /* this is FTP and no proxy */ + CURLcode result=CURLE_OK; + struct SessionHandle *data=conn->data; + char *buf = data->state.buffer; /* this is our buffer */ + + /* the ftp struct is already inited in ftp_connect() */ + struct FTP *ftp = conn->proto.ftp; + + /* Send any QUOTE strings? */ + if(data->set.quote) { + if ((result = ftp_sendquote(conn, data->set.quote)) != CURLE_OK) + return result; + } + + /* This is a re-used connection. Since we change directory to where the + transfer is taking place, we must now get back to the original dir + where we ended up after login: */ + if (conn->bits.reuse && ftp->entrypath) { + if ((result = ftp_cwd(conn, ftp->entrypath)) != CURLE_OK) + return result; + } + + /* change directory first! */ + if(ftp->dir && ftp->dir[0]) { + if ((result = ftp_cwd(conn, ftp->dir)) != CURLE_OK) + return result; + } + + /* Requested time of file? */ + if(data->set.get_filetime && ftp->file) { + result = ftp_getfiletime(conn, ftp->file); + if(result) + return result; + } + + /* If we have selected NOBODY and HEADER, it means that we only want file + information. Which in FTP can't be much more than the file size and + date. */ + if(data->set.no_body && data->set.include_header && ftp->file) { + /* The SIZE command is _not_ RFC 959 specified, and therefor many servers + may not support it! It is however the only way we have to get a file's + size! */ + ssize_t filesize; + + ftp->no_transfer = TRUE; /* this means no actual transfer is made */ + + /* Some servers return different sizes for different modes, and thus we + must set the proper type before we check the size */ + result = ftp_transfertype(conn, data->set.ftp_ascii); + if(result) + return result; + + /* failing to get size is not a serious error */ + result = ftp_getsize(conn, ftp->file, &filesize); + + if(CURLE_OK == result) { + sprintf(buf, "Content-Length: %d\r\n", filesize); + result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); + if(result) + return result; + } + + /* If we asked for a time of the file and we actually got one as + well, we "emulate" a HTTP-style header in our output. */ + +#ifdef HAVE_STRFTIME + if(data->set.get_filetime && data->info.filetime) { + struct tm *tm; +#ifdef HAVE_LOCALTIME_R + struct tm buffer; + tm = (struct tm *)localtime_r(&data->info.filetime, &buffer); +#else + tm = localtime((unsigned long *)&data->info.filetime); +#endif + /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */ + strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S %Z\r\n", + tm); + result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0); + if(result) + return result; + } +#endif + + return CURLE_OK; + } + + if(data->set.no_body) + /* doesn't really transfer any data */ + ftp->no_transfer = TRUE; + /* Get us a second connection up and connected */ + else if(data->set.ftp_use_port) { + /* We have chosen to use the PORT command */ + result = ftp_use_port(conn); + if(CURLE_OK == result) { + /* we have the data connection ready */ + infof(data, "Ordered connect of the data stream with PORT!\n"); + *connected = TRUE; /* mark us "still connected" */ + } + } + else { + /* We have chosen (this is default) to use the PASV command */ + result = ftp_use_pasv(conn, connected); + if(connected) + infof(data, "Connected the data stream with PASV!\n"); + } + + return result; +} + +/*********************************************************************** + * * Curl_ftp() * * This function is registered as 'curl_do' function. It decodes the path @@ -2000,6 +2035,7 @@ CURLcode ftp_perform(struct connectdata *conn) CURLcode Curl_ftp(struct connectdata *conn) { CURLcode retcode; + bool connected; struct SessionHandle *data = conn->data; struct FTP *ftp; @@ -2046,15 +2082,15 @@ CURLcode Curl_ftp(struct connectdata *conn) else ftp->dir = NULL; - retcode = ftp_perform(conn); - - /* clean up here, success or error doesn't matter */ - if(ftp->file) - free(ftp->file); - if(ftp->dir) - free(ftp->dir); + retcode = ftp_perform(conn, &connected); - ftp->file = ftp->dir = NULL; /* zero */ + if(CURLE_OK == retcode) { + if(connected) + retcode = Curl_ftp_nextconnect(conn); + else + /* since we didn't connect now, we want do_more to get called */ + conn->bits.do_more = TRUE; + } return retcode; } @@ -2081,10 +2117,7 @@ CURLcode Curl_ftpsendf(struct connectdata *conn, va_start(ap, fmt); vsnprintf(s, 250, fmt, ap); va_end(ap); - - if(conn->data->set.verbose) - fprintf(conn->data->set.err, "> %s\n", s); - + strcat(s, "\r\n"); /* append a trailing CRLF */ bytes_written=0; @@ -2097,6 +2130,9 @@ CURLcode Curl_ftpsendf(struct connectdata *conn, if(CURLE_OK != res) break; + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, bytes_written); + if(bytes_written != write_len) { write_len -= bytes_written; sptr += bytes_written; @@ -2125,6 +2161,12 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn) free(ftp->entrypath); if(ftp->cache) free(ftp->cache); + if(ftp->file) + free(ftp->file); + if(ftp->dir) + free(ftp->dir); + + ftp->file = ftp->dir = NULL; /* zero */ } return CURLE_OK; } @@ -2136,3 +2178,5 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn) * vim600: fdm=marker * vim: et sw=2 ts=2 sts=2 tw=78 */ + +#endif /* CURL_DISABLE_FTP */ diff --git a/Source/CTest/Curl/ftp.h b/Source/CTest/Curl/ftp.h index a88cc72..2f8c15a 100644 --- a/Source/CTest/Curl/ftp.h +++ b/Source/CTest/Curl/ftp.h @@ -1,37 +1,37 @@ #ifndef __FTP_H #define __FTP_H - -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ + +#ifndef CURL_DISABLE_FTP CURLcode Curl_ftp(struct connectdata *conn); CURLcode Curl_ftp_done(struct connectdata *conn); CURLcode Curl_ftp_connect(struct connectdata *conn); CURLcode Curl_ftp_disconnect(struct connectdata *conn); - CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...); - -/* The kerberos stuff needs this: */ int Curl_GetFTPResponse(char *buf, struct connectdata *conn, int *ftpcode); +CURLcode Curl_ftp_nextconnect(struct connectdata *conn); +#endif #endif diff --git a/Source/CTest/Curl/getenv.c b/Source/CTest/Curl/getenv.c index 66bca30..e19bad2 100644 --- a/Source/CTest/Curl/getenv.c +++ b/Source/CTest/Curl/getenv.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/getinfo.c b/Source/CTest/Curl/getinfo.c index b05e51b..6639833 100644 --- a/Source/CTest/Curl/getinfo.c +++ b/Source/CTest/Curl/getinfo.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -35,6 +35,11 @@ #include <stdlib.h> #endif +/* Make this the last #include */ +#ifdef MALLOCDEBUG +#include "memdebug.h" +#endif + /* * This is supposed to be called in the beginning of a permform() session * and should reset all session-info variables @@ -49,6 +54,7 @@ CURLcode Curl_initinfo(struct SessionHandle *data) pro->t_pretransfer = 0; pro->t_starttransfer = 0; pro->timespent = 0; + pro->t_redirect = 0; info->httpcode = 0; info->httpversion=0; @@ -66,9 +72,9 @@ CURLcode Curl_initinfo(struct SessionHandle *data) CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) { va_list arg; - long *param_longp; - double *param_doublep; - char **param_charp; + long *param_longp=NULL; + double *param_doublep=NULL; + char **param_charp=NULL; va_start(arg, info); switch(info&CURLINFO_TYPEMASK) { @@ -143,6 +149,12 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...) case CURLINFO_CONTENT_LENGTH_UPLOAD: *param_doublep = data->progress.size_ul; break; + case CURLINFO_REDIRECT_TIME: + *param_doublep = data->progress.t_redirect; + break; + case CURLINFO_REDIRECT_COUNT: + *param_longp = data->set.followlocation; + break; case CURLINFO_CONTENT_TYPE: *param_charp = data->info.contenttype; break; diff --git a/Source/CTest/Curl/getinfo.h b/Source/CTest/Curl/getinfo.h index 23fdff1..dd30afb 100644 --- a/Source/CTest/Curl/getinfo.h +++ b/Source/CTest/Curl/getinfo.h @@ -1,27 +1,27 @@ #ifndef __GETINFO_H #define __GETINFO_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...); CURLcode Curl_initinfo(struct SessionHandle *data); diff --git a/Source/CTest/Curl/getpass.c b/Source/CTest/Curl/getpass.c index fd0d6fe..d0f4eda 100644 --- a/Source/CTest/Curl/getpass.c +++ b/Source/CTest/Curl/getpass.c @@ -1,5 +1,5 @@ /* ============================================================================ - * Copyright (C) 1998 Angus Mackay. All rights reserved; + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * * Redistribution and use are freely permitted provided that: * @@ -93,14 +93,10 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) #include "memdebug.h" #endif -/* no perror? make an fprintf! */ -#ifndef HAVE_PERROR -# define perror(x) fprintf(stderr, "Error in: %s\n", x) -#endif - char *getpass_r(const char *prompt, char *buffer, size_t buflen) { FILE *infp; + char infp_fclose = 0; FILE *outfp; RETSIGTYPE (*sigint)(); #ifndef __EMX__ @@ -127,41 +123,30 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) sigtstp = signal(SIGTSTP, SIG_IGN); #endif - if( (infp=fopen("/dev/tty", "r")) == NULL ) - { + infp=fopen("/dev/tty", "r"); + if( NULL == infp ) infp = stdin; - } - if( (outfp=fopen("/dev/tty", "w")) == NULL ) - { - outfp = stderr; - } + else + infp_fclose = 1; + + outfp = stderr; + infd = fileno(infp); outfd = fileno(outfp); /* dissable echo */ #ifdef HAVE_TERMIOS_H - if(tcgetattr(outfd, &orig) != 0) - { - ; /*perror("tcgetattr");*/ - } + tcgetattr(outfd, &orig); + noecho = orig; noecho.c_lflag &= ~ECHO; - if(tcsetattr(outfd, TCSANOW, &noecho) != 0) - { - ; /*perror("tcgetattr");*/ - } + tcsetattr(outfd, TCSANOW, &noecho); #else # ifdef HAVE_TERMIO_H - if(ioctl(outfd, TCGETA, &orig) != 0) - { - ; /*perror("ioctl");*/ - } + ioctl(outfd, TCGETA, &orig); noecho = orig; noecho.c_lflag &= ~ECHO; - if(ioctl(outfd, TCSETA, &noecho) != 0) - { - ; /*perror("ioctl");*/ - } + ioctl(outfd, TCSETA, &noecho); # else # endif #endif @@ -187,16 +172,10 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) * user types more than buflen */ #ifdef HAVE_TERMIOS_H - if(tcsetattr(outfd, TCSAFLUSH, &orig) != 0) - { - ; /*perror("tcgetattr");*/ - } + tcsetattr(outfd, TCSAFLUSH, &orig); #else # ifdef HAVE_TERMIO_H - if(ioctl(outfd, TCSETA, &orig) != 0) - { - ; /*perror("ioctl");*/ - } + ioctl(outfd, TCSETA, &orig); # else # endif #endif @@ -206,6 +185,9 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) signal(SIGTSTP, sigtstp); #endif + if(infp_fclose) + fclose(infp); + return buffer; /* we always return success */ } #endif /* VMS */ diff --git a/Source/CTest/Curl/getpass.h b/Source/CTest/Curl/getpass.h index 249a26e..475d275 100644 --- a/Source/CTest/Curl/getpass.h +++ b/Source/CTest/Curl/getpass.h @@ -1,27 +1,27 @@ #ifndef __GETPASS_H #define __GETPASS_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #ifndef HAVE_GETPASS_R /* If there's a system-provided function named like this, we trust it is also found in one of the standard headers. */ diff --git a/Source/CTest/Curl/hash.c b/Source/CTest/Curl/hash.c index 584c30e..56e7077 100644 --- a/Source/CTest/Curl/hash.c +++ b/Source/CTest/Curl/hash.c @@ -1,30 +1,31 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" #include <string.h> #include <stdlib.h> + #include "hash.h" #include "llist.h" @@ -34,55 +35,45 @@ #endif -static unsigned long -curl_hash_str(const char *key, unsigned int key_length) +/* {{{ static unsigned long _hash_str (const char *, size_t) + */ +static unsigned long +_hash_str (const char *key, size_t key_length) { - register unsigned long h = 0; - register unsigned long g; - register char *p = (char *) key; - register char *end = (char *) key + key_length; - - while (p < end) { - h = (h << 4) + *p++; - if ((g = (h & 0xF0000000))) { - h = h ^ (g >> 24); - h = h ^ g; - } + char *end = (char *) key + key_length; + unsigned long h = 5381; + + while (key < end) { + h += h << 5; + h ^= (unsigned long) *key++; } return h; } +/* }}} */ -static unsigned long -curl_hash_num(unsigned long key) -{ - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += (key << 11); - key ^= (key >> 16); - - return key; -} - +/* {{{ static void _hash_element_dtor (void *, void *) + */ static void -hash_element_dtor(void *u, void *ele) +_hash_element_dtor (void *user, void *element) { - curl_hash_element *e = (curl_hash_element *) ele; - curl_hash *h = (curl_hash *) u; - - if (e->key.type == CURL_HASH_KEY_IS_STRING) { - free(e->key.value.str.val); + curl_hash *h = (curl_hash *) user; + curl_hash_element *e = (curl_hash_element *) element; + + if (e->key) { + free(e->key); } + h->dtor(e->ptr); free(e); - e = NULL; } +/* }}} */ +/* {{{ void curl_hash_init (curl_hash *, int, curl_hash_dtor) + */ void -curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor) +Curl_hash_init (curl_hash *h, int slots, curl_hash_dtor dtor) { int i; @@ -91,116 +82,110 @@ curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor) h->slots = slots; h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *)); - for (i = 0; i < h->slots; ++i) { - h->table[i] = curl_llist_alloc((curl_llist_dtor) hash_element_dtor); + for (i = 0; i < slots; ++i) { + h->table[i] = Curl_llist_alloc((curl_llist_dtor) _hash_element_dtor); } } +/* }}} */ +/* {{{ curl_hash *curl_hash_alloc (int, curl_hash_dtor) + */ curl_hash * -curl_hash_alloc(int slots, curl_hash_dtor dtor) +Curl_hash_alloc (int slots, curl_hash_dtor dtor) { curl_hash *h; - h = (curl_hash *)malloc(sizeof(curl_hash)); - if(NULL == h) + h = (curl_hash *) malloc(sizeof(curl_hash)); + if (NULL == h) return NULL; - curl_hash_init(h, slots, dtor); + Curl_hash_init(h, slots, dtor); return h; } +/* }}} */ -#define FIND_SLOT(__h, __s_key, __s_key_len, __n_key) \ - ((__s_key ? curl_hash_str(__s_key, __s_key_len) : curl_hash_num(__n_key)) % (__h)->slots) - -#define KEY_CREATE(__k, __s_key, __s_key_len, __n_key, __dup) \ - if (__s_key) { \ - if (__dup) { \ - (__k)->value.str.val = (char *) malloc(__s_key_len); \ - memcpy((__k)->value.str.val, __s_key, __s_key_len); \ - } else { \ - (__k)->value.str.val = __s_key; \ - } \ - (__k)->value.str.len = __s_key_len; \ - (__k)->type = CURL_HASH_KEY_IS_STRING; \ - } else { \ - (__k)->value.num = __n_key; \ - (__k)->type = CURL_HASH_KEY_IS_NUM; \ +/* {{{ static int _hash_key_compare (char *, size_t, char *, size_t) + */ +static int +_hash_key_compare (char *key1, size_t key1_len, char *key2, size_t key2_len) +{ + if (key1_len == key2_len && + *key1 == *key2 && + memcmp(key1, key2, key1_len) == 0) { + return 1; } -#define MIN(a, b) (a > b ? b : a) + return 0; +} +/* }}} */ -static int -curl_hash_key_compare(curl_hash_key *key1, curl_hash_key *key2) +/* {{{ static int _mk_hash_element (curl_hash_element **, char *, size_t, const void *) + */ +static int +_mk_hash_element (curl_hash_element **e, char *key, size_t key_len, const void *p) { - if (key1->type == CURL_HASH_KEY_IS_NUM) { - if (key2->type == CURL_HASH_KEY_IS_STRING) - return 0; + *e = (curl_hash_element *) malloc(sizeof(curl_hash_element)); + (*e)->key = strdup(key); + (*e)->key_len = key_len; + (*e)->ptr = (void *) p; + return 0; +} +/* }}} */ - if (key1->value.num == key2->value.num) - return 1; - } else { - if (key2->type == CURL_HASH_KEY_IS_NUM) - return 0; +#define find_slot(__h, __k, __k_len) (_hash_str(__k, __k_len) % (__h)->slots) - if (memcmp(key1->value.str.val, key2->value.str.val, - MIN(key1->value.str.len, key2->value.str.len)) == 0) - return 1; - } +#define FETCH_LIST \ + curl_llist *l = h->table[find_slot(h, key, key_len)] - return 0; -} +/* {{{ int curl_hash_add (curl_hash *, char *, size_t, const void *) + */ int -curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len, - unsigned long num_key, const void *p) +Curl_hash_add (curl_hash *h, char *key, size_t key_len, const void *p) { - curl_hash_element *e; - curl_hash_key tmp; - curl_llist *l; + curl_hash_element *he; curl_llist_element *le; - int slot; - - slot = FIND_SLOT(h, str_key, str_key_len, num_key); - l = h->table[slot]; - KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0); - for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) { - if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) { - curl_hash_element *to_update = CURL_LLIST_VALP(le); - h->dtor(to_update->ptr); - to_update->ptr = (void *) p; + FETCH_LIST; + + for (le = CURL_LLIST_HEAD(l); + le != NULL; + le = CURL_LLIST_NEXT(le)) { + he = (curl_hash_element *) CURL_LLIST_VALP(le); + if (_hash_key_compare(he->key, he->key_len, key, key_len)) { + h->dtor(he->ptr); + he->ptr = (void *) p; return 1; } } - e = (curl_hash_element *) malloc(sizeof(curl_hash_element)); - KEY_CREATE(&e->key, str_key, str_key_len, num_key, 1); - e->ptr = (void *) p; + if (_mk_hash_element(&he, key, key_len, p) != 0) + return 0; - if (curl_llist_insert_next(l, CURL_LLIST_TAIL(l), e)) { + if (Curl_llist_insert_next(l, CURL_LLIST_TAIL(l), he)) { ++h->size; return 1; - } else { - return 0; } + + return 0; } +/* }}} */ +/* {{{ int curl_hash_delete (curl_hash *, char *, size_t) + */ int -curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len, - unsigned long num_key) +Curl_hash_delete(curl_hash *h, char *key, size_t key_len) { - curl_llist *l; + curl_hash_element *he; curl_llist_element *le; - curl_hash_key tmp; - int slot; - - slot = FIND_SLOT(h, str_key, str_key_len, num_key); - l = h->table[slot]; - - KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0); - for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) { - if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) { - curl_llist_remove(l, le, (void *) h); + FETCH_LIST; + + for (le = CURL_LLIST_HEAD(l); + le != NULL; + le = CURL_LLIST_NEXT(le)) { + he = CURL_LLIST_VALP(le); + if (_hash_key_compare(he->key, he->key_len, key, key_len)) { + Curl_llist_remove(l, le, (void *) h); --h->size; return 1; } @@ -208,73 +193,111 @@ curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len, return 0; } +/* }}} */ -int -curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len, - unsigned long num_key, void **p) +/* {{{ int curl_hash_pick (curl_hash *, char *, size_t, void **) + */ +void * +Curl_hash_pick(curl_hash *h, char *key, size_t key_len) { - curl_llist *l; curl_llist_element *le; - curl_hash_key tmp; - int slot; - - slot = FIND_SLOT(h, str_key, str_key_len, num_key); - l = h->table[slot]; - - KEY_CREATE(&tmp, str_key, str_key_len, num_key, 0); - for (le = CURL_LLIST_HEAD(l); le != NULL; le = CURL_LLIST_NEXT(le)) { - if (curl_hash_key_compare(&tmp, &((curl_hash_element *) CURL_LLIST_VALP(le))->key)) { - *p = ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr; - return 1; + curl_hash_element *he; + FETCH_LIST; + + for (le = CURL_LLIST_HEAD(l); + le != NULL; + le = CURL_LLIST_NEXT(le)) { + he = CURL_LLIST_VALP(le); + if (_hash_key_compare(he->key, he->key_len, key, key_len)) { + return he->ptr; } } - return 0; + return NULL; } +/* }}} */ +/* {{{ void curl_hash_apply (curl_hash *, void *, void (*)(void *, curl_hash_element *)) + */ void -curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *)) +Curl_hash_apply(curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)) { curl_llist_element *le; int i; for (i = 0; i < h->slots; ++i) { - for (le = CURL_LLIST_HEAD(h->table[i]); le != NULL; le = CURL_LLIST_NEXT(le)) { - cb(user, (curl_hash_element *) CURL_LLIST_VALP(le)); + for (le = CURL_LLIST_HEAD(h->table[i]); + le != NULL; + le = CURL_LLIST_NEXT(le)) { + curl_hash_element *el = CURL_LLIST_VALP(le); + cb(user, el->ptr); } } } +/* }}} */ +/* {{{ void curl_hash_clean (curl_hash *) + */ void -curl_hash_clean(curl_hash *h) +Curl_hash_clean(curl_hash *h) { int i; for (i = 0; i < h->slots; ++i) { - curl_llist_destroy(h->table[i], (void *) h); + Curl_llist_destroy(h->table[i], (void *) h); } free(h->table); - h->table = NULL; } +/* }}} */ -size_t -curl_hash_count(curl_hash *h) +/* {{{ void curl_hash_clean_with_criterium (curl_hash *, void *, + int (*)(void *, void *)) + */ +void +Curl_hash_clean_with_criterium(curl_hash *h, void *user, + int (*comp)(void *, void *)) +{ + curl_llist_element *le; + curl_llist_element *lnext; + int i; + + for (i = 0; i < h->slots; ++i) { + le = CURL_LLIST_HEAD(h->table[i]); + while(le != NULL) + if (comp(user, ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr)) { + lnext = CURL_LLIST_NEXT(le); + Curl_llist_remove(h->table[i], le, (void *) h); + --h->size; + le = lnext; + } + else + le = CURL_LLIST_NEXT(le); + } +} + +/* {{{ int curl_hash_count (curl_hash *) + */ +int +Curl_hash_count(curl_hash *h) { return h->size; } +/* }}} */ +/* {{{ void curl_hash_destroy (curl_hash *) + */ void -curl_hash_destroy(curl_hash *h) +Curl_hash_destroy(curl_hash *h) { - if (!h) { + if (!h) return; - } - curl_hash_clean(h); + Curl_hash_clean(h); free(h); - h = NULL; } +/* }}} */ /* * local variables: diff --git a/Source/CTest/Curl/hash.h b/Source/CTest/Curl/hash.h index d6117ce..c3464c3 100644 --- a/Source/CTest/Curl/hash.h +++ b/Source/CTest/Curl/hash.h @@ -1,27 +1,27 @@ #ifndef __HASH_H #define __HASH_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -29,9 +29,6 @@ #include "llist.h" -#define CURL_HASH_KEY_IS_STRING 0 -#define CURL_HASH_KEY_IS_NUM 1 - typedef void (*curl_hash_dtor)(void *); typedef struct _curl_hash { @@ -41,45 +38,31 @@ typedef struct _curl_hash { size_t size; } curl_hash; -typedef struct _curl_hash_key { - union { - struct { - char *val; - unsigned int len; - } str; - - unsigned long num; - } value; - - int type; -} curl_hash_key; - typedef struct _curl_hash_element { - curl_hash_key key; - void *ptr; + void *ptr; + char *key; + size_t key_len; } curl_hash_element; -void curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor); -curl_hash *curl_hash_alloc(int slots, curl_hash_dtor dtor); -int curl_hash_add_or_update(curl_hash *h, char *str_key, unsigned int str_key_len, - unsigned long num_key, const void *p); -int curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_len, - unsigned long num_key); -int curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len, - unsigned long num_key, void **p); -void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *)); -size_t curl_hash_count(curl_hash *h); -void curl_hash_clean(curl_hash *h); -void curl_hash_destroy(curl_hash *h); - -#define curl_hash_find(h, key, key_len, p) curl_hash_extended_find(h, key, key_len, 0, p) -#define curl_hash_delete(h, key, key_len) curl_hash_extended_delete(h, key, key_len, 0) -#define curl_hash_add(h, key, key_len, p) curl_hash_add_or_update(h, key, key_len, 0, p) -#define curl_hash_update curl_hash_add -#define curl_hash_index_find(h, key, p) curl_hash_extended_find(h, NULL, 0, key, p) -#define curl_hash_index_delete(h, key) curl_hash_extended_delete(h, NULL, 0, key) -#define curl_hash_index_add(h, key, p) curl_hash_add_or_update(h, NULL, 0, key, p) -#define curl_hash_index_update curl_hash_index_add +void Curl_hash_init(curl_hash *, int, curl_hash_dtor); +curl_hash *Curl_hash_alloc(int, curl_hash_dtor); +int Curl_hash_add(curl_hash *, char *, size_t, const void *); +int Curl_hash_delete(curl_hash *h, char *key, size_t key_len); +void *Curl_hash_pick(curl_hash *, char *, size_t); +void Curl_hash_apply(curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)); +int Curl_hash_count(curl_hash *h); +void Curl_hash_clean(curl_hash *h); +void Curl_hash_clean_with_criterium(curl_hash *h, void *user, int (*comp)(void *, void *)); +void Curl_hash_destroy(curl_hash *h); #endif + +/* + * local variables: + * eval: (load-file "../curl-mode.el") + * end: + * vim600: fdm=marker + * vim: et sw=2 ts=2 sts=2 tw=78 + */ diff --git a/Source/CTest/Curl/hostip.c b/Source/CTest/Curl/hostip.c index 489dfab..07fb1d2 100644 --- a/Source/CTest/Curl/hostip.c +++ b/Source/CTest/Curl/hostip.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -56,6 +56,10 @@ #endif #endif +#ifdef HAVE_SETJMP_H +#include <setjmp.h> +#endif + #include "urldata.h" #include "sendf.h" #include "hostip.h" @@ -76,10 +80,15 @@ static curl_hash hostname_cache; static int host_cache_initialized; +static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data, + char *hostname, + int port, + char **bufp); + void Curl_global_host_cache_init(void) { if (!host_cache_initialized) { - curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo); + Curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo); host_cache_initialized = 1; } } @@ -92,16 +101,11 @@ curl_hash *Curl_global_host_cache_get(void) void Curl_global_host_cache_dtor(void) { if (host_cache_initialized) { - curl_hash_clean(&hostname_cache); + Curl_hash_clean(&hostname_cache); host_cache_initialized = 0; } } -struct curl_dns_cache_entry { - Curl_addrinfo *addr; - time_t timestamp; -}; - /* count the number of characters that an integer takes up */ static int _num_chars(int i) { @@ -125,7 +129,7 @@ static int _num_chars(int i) /* Create a hostcache id */ static char * -_create_hostcache_id(char *server, int port, ssize_t *entry_len) +create_hostcache_id(char *server, int port, ssize_t *entry_len) { char *id = NULL; @@ -152,70 +156,132 @@ _create_hostcache_id(char *server, int port, ssize_t *entry_len) return id; } +struct hostcache_prune_data { + int cache_timeout; + int now; +}; + +static int +hostcache_timestamp_remove(void *datap, void *hc) +{ + struct hostcache_prune_data *data = + (struct hostcache_prune_data *) datap; + struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc; + + if ((data->now - c->timestamp < data->cache_timeout) || + c->inuse) { + /* please don't remove */ + return 0; + } + + /* fine, remove */ + return 1; +} + +static void +hostcache_prune(curl_hash *hostcache, int cache_timeout, int now) +{ + struct hostcache_prune_data user; + + user.cache_timeout = cache_timeout; + user.now = now; + + Curl_hash_clean_with_criterium(hostcache, + (void *) &user, + hostcache_timestamp_remove); +} + +#if defined(MALLOCDEBUG) && defined(AGGRESIVE_TEST) +/* Called from Curl_done() to check that there's no DNS cache entry with + a non-zero counter left. */ +void Curl_scan_cache_used(void *user, void *ptr) +{ + struct Curl_dns_entry *e = ptr; + (void)user; /* prevent compiler warning */ + if(e->inuse) { + fprintf(stderr, "*** WARNING: locked DNS cache entry detected: %s\n", + e->entry_id); + /* perform a segmentation fault to draw attention */ + *(void **)0 = 0; + } +} +#endif + /* Macro to save redundant free'ing of entry_id */ -#define _hostcache_return(__v) \ +#define HOSTCACHE_RETURN(dns) \ { \ free(entry_id); \ - return (__v); \ + return dns; \ } -Curl_addrinfo *Curl_resolv(struct SessionHandle *data, - char *hostname, - int port, - char **bufp) +#ifdef HAVE_SIGSETJMP +/* Beware this is a global and unique instance */ +sigjmp_buf curl_jmpenv; +#endif + +struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data, + char *hostname, + int port) { char *entry_id = NULL; - struct curl_dns_cache_entry *p = NULL; + struct Curl_dns_entry *dns = NULL; ssize_t entry_len; time_t now; - - /* If the host cache timeout is 0, we don't do DNS cach'ing - so fall through */ - if (data->set.dns_cache_timeout == 0) { - return Curl_getaddrinfo(data, hostname, port, bufp); + char *bufp; + +#ifdef HAVE_SIGSETJMP + /* this allows us to time-out from the name resolver, as the timeout + will generate a signal and we will siglongjmp() from that here */ + if(!data->set.no_signal && sigsetjmp(curl_jmpenv, 1)) { + /* this is coming from a siglongjmp() */ + failf(data, "name lookup time-outed"); + return NULL; } +#endif /* Create an entry id, based upon the hostname and port */ entry_len = strlen(hostname); - entry_id = _create_hostcache_id(hostname, port, &entry_len); - /* If we can't create the entry id, don't cache, just fall-through - to the plain Curl_getaddrinfo() */ - if (!entry_id) { - return Curl_getaddrinfo(data, hostname, port, bufp); - } + entry_id = create_hostcache_id(hostname, port, &entry_len); + /* If we can't create the entry id, fail */ + if (!entry_id) + return NULL; - time(&now); /* See if its already in our dns cache */ - if (entry_id && curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) { - /* Do we need to check for a cache timeout? */ - if (data->set.dns_cache_timeout != -1) { - /* Return if the entry has not timed out */ - if ((now - p->timestamp) < data->set.dns_cache_timeout) { - _hostcache_return(p->addr); - } + dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1); + + if (!dns) { + Curl_addrinfo *addr = my_getaddrinfo(data, hostname, port, &bufp); + + if (!addr) { + HOSTCACHE_RETURN(NULL); } - else { - _hostcache_return(p->addr); + + /* Create a new cache entry */ + dns = (struct Curl_dns_entry *) malloc(sizeof(struct Curl_dns_entry)); + if (!dns) { + Curl_freeaddrinfo(addr); + HOSTCACHE_RETURN(NULL); } - } - /* Create a new cache entry */ - p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry)); - if (!p) { - _hostcache_return(NULL); + dns->inuse = 0; + dns->addr = addr; + /* Save it in our host cache */ + Curl_hash_add(data->hostcache, entry_id, entry_len+1, (const void *) dns); } + time(&now); - p->addr = Curl_getaddrinfo(data, hostname, port, bufp); - if (!p->addr) { - free(p); - _hostcache_return(NULL); - } - p->timestamp = now; + dns->timestamp = now; + dns->inuse++; /* mark entry as in-use */ +#ifdef MALLOCDEBUG + dns->entry_id = entry_id; +#endif - /* Save it in our host cache */ - curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p); + /* Remove outdated and unused entries from the hostcache */ + hostcache_prune(data->hostcache, + data->set.dns_cache_timeout, + now); - _hostcache_return(p->addr); + HOSTCACHE_RETURN(dns); } /* @@ -225,7 +291,7 @@ Curl_addrinfo *Curl_resolv(struct SessionHandle *data, */ void Curl_freeaddrinfo(void *freethis) { - struct curl_dns_cache_entry *p = (struct curl_dns_cache_entry *) freethis; + struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis; #ifdef ENABLE_IPV6 freeaddrinfo(p->addr); @@ -283,23 +349,37 @@ void curl_freeaddrinfo(struct addrinfo *freethis, * memory we need to free after use. That meory *MUST* be freed with * Curl_freeaddrinfo(), nothing else. */ -Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, - char *hostname, - int port, - char **bufp) +static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data, + char *hostname, + int port, + char **bufp) { struct addrinfo hints, *res; int error; char sbuf[NI_MAXSERV]; - + int s, pf = PF_UNSPEC; + + /* see if we have an IPv6 stack */ + s = socket(PF_INET6, SOCK_DGRAM, 0); + if (s < 0) + /* Some non-IPv6 stacks have been found to make very slow name resolves + * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if + * the stack seems to be a non-ipv6 one. */ + pf = PF_INET; + else + /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest + * possible checks. And close the socket again. + */ + sclose(s); + memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_INET; + hints.ai_family = pf; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; snprintf(sbuf, sizeof(sbuf), "%d", port); error = getaddrinfo(hostname, sbuf, &hints, &res); if (error) { - infof(data, "getaddrinfo(3) failed for %s\n", hostname); + infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port); return NULL; } *bufp=(char *)res; /* make it point to the result struct */ @@ -309,22 +389,24 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, #else /* following code is IPv4-only */ #ifndef HAVE_GETHOSTBYNAME_R +static void hostcache_fixoffset(struct hostent *h, int offset); /** * Performs a "deep" copy of a hostent into a buffer (returns a pointer to the * copy). Make absolutely sure the destination buffer is big enough! * * Keith McGuigan * 10/3/2001 */ -static struct hostent* pack_hostent(char* buf, struct hostent* orig) +static struct hostent* pack_hostent(char** buf, struct hostent* orig) { - char* bufptr; + char *bufptr; + char *newbuf; struct hostent* copy; int i; - char* str; + char *str; int len; - bufptr = buf; + bufptr = *buf; copy = (struct hostent*)bufptr; bufptr += sizeof(struct hostent); @@ -334,10 +416,12 @@ static struct hostent* pack_hostent(char* buf, struct hostent* orig) bufptr += len; /* we align on even 64bit boundaries for safety */ -#define MEMALIGN(x) (((unsigned long)(x)&0xfffffff8)+8) +#define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7))) /* This must be aligned properly to work on many CPU architectures! */ - copy->h_aliases = (char**)MEMALIGN(bufptr); + bufptr = MEMALIGN(bufptr); + + copy->h_aliases = (char**)bufptr; /* Figure out how many aliases there are */ for (i = 0; orig->h_aliases[i] != NULL; ++i); @@ -359,7 +443,7 @@ static struct hostent* pack_hostent(char* buf, struct hostent* orig) copy->h_length = orig->h_length; /* align it for (at least) 32bit accesses */ - bufptr = (char *)MEMALIGN(bufptr); + bufptr = MEMALIGN(bufptr); copy->h_addr_list = (char**)bufptr; @@ -380,6 +464,18 @@ static struct hostent* pack_hostent(char* buf, struct hostent* orig) } copy->h_addr_list[i] = NULL; + /* now, shrink the allocated buffer to the size we actually need, which + most often is only a fraction of the original alloc */ + newbuf=(char *)realloc(*buf, (int)bufptr-(int)(*buf)); + + /* if the alloc moved, we need to adjust things again */ + if(newbuf != *buf) + hostcache_fixoffset((struct hostent*)newbuf, (int)newbuf-(int)*buf); + + /* setup the return */ + *buf = newbuf; + copy = (struct hostent*)newbuf; + return copy; } #endif @@ -405,18 +501,34 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len) return (addr); } -/* The original code to this function was once stolen from the Dancer source - code, written by Bjorn Reese, it has since been patched and modified - considerably. */ - #ifndef INADDR_NONE #define INADDR_NONE (in_addr_t) ~0 #endif -Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, - char *hostname, - int port, - char **bufp) +static void hostcache_fixoffset(struct hostent *h, int offset) +{ + int i=0; + h->h_name=(char *)((long)h->h_name+offset); + h->h_aliases=(char **)((long)h->h_aliases+offset); + while(h->h_aliases[i]) { + h->h_aliases[i]=(char *)((long)h->h_aliases[i]+offset); + i++; + } + h->h_addr_list=(char **)((long)h->h_addr_list+offset); + i=0; + while(h->h_addr_list[i]) { + h->h_addr_list[i]=(char *)((long)h->h_addr_list[i]+offset); + i++; + } +} + +/* The original code to this function was once stolen from the Dancer source + code, written by Bjorn Reese, it has since been patched and modified + considerably. */ +static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data, + char *hostname, + int port, + char **bufp) { struct hostent *h = NULL; in_addr_t in; @@ -427,51 +539,116 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, * everything. OSF1 is known to require at least 8872 bytes. The buffer * required for storing all possible aliases and IP numbers is according to * Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */ - int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE); - if(!buf) - return NULL; /* major failure */ - *bufp = (char *)buf; - port=0; /* unused in IPv4 code */ ret = 0; /* to prevent the compiler warning */ if ( (in=inet_addr(hostname)) != INADDR_NONE ) { struct in_addr *addrentry; - - h = (struct hostent*)buf; - h->h_addr_list = (char**)(buf + sizeof(*h)); - addrentry = (struct in_addr*)(h->h_addr_list + 2); + struct namebuf { + struct hostent hostentry; + char *h_addr_list[2]; + struct in_addr addrentry; + char h_name[128]; + } *buf = (struct namebuf *)malloc(sizeof(struct namebuf)); + if(!buf) + return NULL; /* major failure */ + *bufp = (char *)buf; + + h = &buf->hostentry; + h->h_addr_list = &buf->h_addr_list[0]; + addrentry = &buf->addrentry; addrentry->s_addr = in; h->h_addr_list[0] = (char*)addrentry; h->h_addr_list[1] = NULL; h->h_addrtype = AF_INET; h->h_length = sizeof(*addrentry); - h->h_name = *(h->h_addr_list) + h->h_length; - /* bad one h->h_name = (char*)(h->h_addr_list + h->h_length); */ - MakeIP(ntohl(in),h->h_name, CURL_NAMELOOKUP_SIZE - (long)(h->h_name) + (long)buf); + h->h_name = &buf->h_name[0]; + MakeIP(ntohl(in), h->h_name, sizeof(buf->h_name)); } #if defined(HAVE_GETHOSTBYNAME_R) else { int h_errnop; + int res=ERANGE; + int step_size=200; + int *buf = (int *)malloc(CURL_NAMELOOKUP_SIZE); + if(!buf) + return NULL; /* major failure */ + *bufp=(char *)buf; + /* Workaround for gethostbyname_r bug in qnx nto. It is also _required_ for some of these functions. */ memset(buf, 0, CURL_NAMELOOKUP_SIZE); #ifdef HAVE_GETHOSTBYNAME_R_5 /* Solaris, IRIX and more */ - if ((h = gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - CURL_NAMELOOKUP_SIZE - sizeof(struct hostent), - &h_errnop)) == NULL ) + (void)res; /* prevent compiler warning */ + while(!h) { + h = gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + step_size - sizeof(struct hostent), + &h_errnop); + + /* If the buffer is too small, it returns NULL and sets errno to + ERANGE. The errno is thread safe if this is compiled with + -D_REENTRANT as then the 'errno' variable is a macro defined to + get used properly for threads. */ + + if(h || (errno != ERANGE)) + break; + + step_size+=200; + } + +#ifdef MALLOCDEBUG + infof(data, "gethostbyname_r() uses %d bytes\n", step_size); +#endif + + if(h) { + int offset; + h=(struct hostent *)realloc(buf, step_size); + offset=(long)h-(long)buf; + hostcache_fixoffset(h, offset); + buf=(int *)h; + *bufp=(char *)buf; + } + else #endif #ifdef HAVE_GETHOSTBYNAME_R_6 /* Linux */ - if( gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - CURL_NAMELOOKUP_SIZE - sizeof(struct hostent), - &h, /* DIFFERENCE */ - &h_errnop)) + do { + res=gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + step_size - sizeof(struct hostent), + &h, /* DIFFERENCE */ + &h_errnop); + /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a + sudden this function seems to be setting EAGAIN if the given buffer + size is too small. Previous versions are known to return ERANGE for + the same. */ + + if((ERANGE == res) || (EAGAIN == res)) { + step_size+=200; + continue; + } + break; + } while(1); + + if(!h) /* failure */ + res=1; + +#ifdef MALLOCDEBUG + infof(data, "gethostbyname_r() uses %d bytes\n", step_size); +#endif + if(!res) { + int offset; + h=(struct hostent *)realloc(buf, step_size); + offset=(long)h-(long)buf; + hostcache_fixoffset(h, offset); + buf=(int *)h; + *bufp=(char *)buf; + } + else #endif #ifdef HAVE_GETHOSTBYNAME_R_3 /* AIX, Digital Unix, HPUX 10, more? */ @@ -484,8 +661,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, * size dilemma. */ ret = gethostbyname_r(hostname, - (struct hostent *)buf, - (struct hostent_data *)(buf + sizeof(struct hostent))); + (struct hostent *)buf, + (struct hostent_data *)((char *)buf + sizeof(struct hostent))); else ret = -1; /* failure, too smallish buffer size */ @@ -504,14 +681,17 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, else { if ((h = gethostbyname(hostname)) == NULL ) { infof(data, "gethostbyname(2) failed for %s\n", hostname); - free(buf); *bufp=NULL; } else + { + char *buf=(char *)malloc(CURL_NAMELOOKUP_SIZE); /* we make a copy of the hostent right now, right here, as the static one we got a pointer to might get removed when we don't want/expect that */ - h = pack_hostent((char *)buf, h); + h = pack_hostent(&buf, h); + *bufp=(char *)buf; + } #endif } return (h); diff --git a/Source/CTest/Curl/hostip.h b/Source/CTest/Curl/hostip.h index 6910071..78a17e2 100644 --- a/Source/CTest/Curl/hostip.h +++ b/Source/CTest/Curl/hostip.h @@ -1,28 +1,29 @@ #ifndef __HOSTIP_H #define __HOSTIP_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ +#include "setup.h" #include "hash.h" struct addrinfo; @@ -35,16 +36,34 @@ curl_hash *Curl_global_host_cache_get(void); #define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache) -Curl_addrinfo *Curl_resolv(struct SessionHandle *data, - char *hostname, - int port, - char **bufp); +struct Curl_dns_entry { + Curl_addrinfo *addr; + time_t timestamp; + long inuse; /* use-counter, make very sure you decrease this + when you're done using the address you received */ +#ifdef MALLOCDEBUG + char *entry_id; +#endif +}; + +/* + * Curl_resolv() returns an entry with the info for the specified host + * and port. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ + +struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data, + char *hostname, + int port); + +/* unlock a previously resolved dns entry */ +#define Curl_resolv_unlock(dns) dns->inuse-- + +/* for debugging purposes only: */ +void Curl_scan_cache_used(void *user, void *ptr); -/* Get name info */ -Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data, - char *hostname, - int port, - char **bufp); /* free name info */ void Curl_freeaddrinfo(void *freethis); diff --git a/Source/CTest/Curl/http.c b/Source/CTest/Curl/http.c index 1413618..24794e2 100644 --- a/Source/CTest/Curl/http.c +++ b/Source/CTest/Curl/http.c @@ -1,28 +1,29 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" +#ifndef CURL_DISABLE_HTTP /* -- WIN32 approved -- */ #include <stdio.h> #include <string.h> @@ -133,12 +134,6 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, char *ptr; int size; - if(conn->data->set.verbose) { - fputs("> ", conn->data->set.err); - /* this data _may_ contain binary stuff */ - fwrite(in->buffer, in->size_used, 1, conn->data->set.err); - } - /* The looping below is required since we use non-blocking sockets, but due to the circumstances we will just loop and try again and again etc */ @@ -150,6 +145,10 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, if(CURLE_OK != res) break; + if(conn->data->set.verbose) + /* this data _may_ contain binary stuff */ + Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount); + if(amount != size) { size -= amount; ptr += amount; @@ -163,7 +162,7 @@ CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in, free(in->buffer); free(in); - *bytes_written = amount; + *bytes_written += amount; return res; } @@ -364,11 +363,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, the line isn't really terminated until the LF comes */ /* output debug output if that is requested */ - if(data->set.verbose) { - fputs("< ", data->set.err); - fwrite(line_start, perline, 1, data->set.err); - /* no need to output LF here, it is part of the data */ - } + if(data->set.verbose) + Curl_debug(data, CURLINFO_DATA_IN, line_start, perline); if('\r' == line_start[0]) { /* end of headers */ @@ -392,7 +388,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, } /* while there's buffer left and loop is requested */ if(error) - return CURLE_READ_ERROR; + return CURLE_RECV_ERROR; if(200 != httperror) { if(407 == httperror) @@ -400,7 +396,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, failf(data, "Proxy requires authorization!"); else failf(data, "Received error code %d from proxy", httperror); - return CURLE_READ_ERROR; + return CURLE_RECV_ERROR; } infof (data, "Proxy replied to CONNECT request\n"); @@ -424,7 +420,7 @@ CURLcode Curl_http_connect(struct connectdata *conn) * has occured, can we start talking SSL */ - if(data->change.proxy && + if(conn->bits.httpproxy && ((conn->protocol & PROT_HTTPS) || data->set.tunnel_thru_httpproxy)) { /* either HTTPS over proxy, OR explicitly asked for a tunnel */ @@ -453,23 +449,21 @@ CURLcode Curl_http_connect(struct connectdata *conn) CURLcode Curl_http_done(struct connectdata *conn) { struct SessionHandle *data; - long *bytecount = &conn->bytecount; struct HTTP *http; data=conn->data; http=conn->proto.http; if(HTTPREQ_POST_FORM == data->set.httpreq) { - *bytecount = http->readbytecount + http->writebytecount; + conn->bytecount = http->readbytecount + http->writebytecount; Curl_formclean(http->sendit); /* Now free that whole lot */ data->set.fread = http->storefread; /* restore */ data->set.in = http->in; /* restore */ } - else if(HTTPREQ_PUT == data->set.httpreq) { - *bytecount = http->readbytecount + http->writebytecount; - } + else if(HTTPREQ_PUT == data->set.httpreq) + conn->bytecount = http->readbytecount + http->writebytecount; if(0 == (http->readbytecount + conn->headerbytecount)) { /* nothing was read from the HTTP server, this can't be right @@ -491,7 +485,7 @@ CURLcode Curl_http(struct connectdata *conn) struct Cookie *co=NULL; /* no cookies from start */ char *ppath = conn->ppath; /* three previous function arguments */ char *host = conn->name; - long *bytecount = &conn->bytecount; + const char *te = ""; /* tranfer-encoding */ if(!conn->proto.http) { /* Only allocate this struct if we don't already have it! */ @@ -553,12 +547,20 @@ CURLcode Curl_http(struct connectdata *conn) conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie); } + if(conn->bits.upload_chunky) { + if(!checkheaders(data, "Transfer-Encoding:")) { + te = "Transfer-Encoding: chunked\r\n"; + } + /* else + our header was already added, what to do now? */ + } + if(data->cookies) { co = Curl_cookie_getlist(data->cookies, host, ppath, - conn->protocol&PROT_HTTPS?TRUE:FALSE); + (conn->protocol&PROT_HTTPS?TRUE:FALSE)); } - if (data->change.proxy && + if (data->change.proxy && *data->change.proxy && !data->set.tunnel_thru_httpproxy && !(conn->protocol&PROT_HTTPS)) { /* The path sent to the proxy is in fact the entire URL */ @@ -567,7 +569,13 @@ CURLcode Curl_http(struct connectdata *conn) if(HTTPREQ_POST_FORM == data->set.httpreq) { /* we must build the whole darned post sequence first, so that we have a size of the whole shebang before we start to send it */ - http->sendit = Curl_getFormData(data->set.httppost, &http->postsize); + result = Curl_getFormData(&http->sendit, data->set.httppost, + &http->postsize); + if(CURLE_OK != result) { + /* Curl_getFormData() doesn't use failf() */ + failf(data, "failed creating formpost data"); + return result; + } } if(!checkheaders(data, "Host:")) { @@ -579,13 +587,22 @@ CURLcode Curl_http(struct connectdata *conn) if(conn->allocptr.host) free(conn->allocptr.host); + /* When building Host: headers, we must put the host name within + [brackets] if the host name is a plain IPv6-address. RFC2732-style. */ + if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) || (!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) ) /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include the port number in the host string */ - conn->allocptr.host = aprintf("Host: %s\r\n", host); + conn->allocptr.host = aprintf("Host: %s%s%s\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":""); else - conn->allocptr.host = aprintf("Host: %s:%d\r\n", host, + conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n", + conn->bits.ipv6_ip?"[":"", + host, + conn->bits.ipv6_ip?"]":"", conn->remote_port); } @@ -661,6 +678,9 @@ CURLcode Curl_http(struct connectdata *conn) */ if((data->set.httpreq == HTTPREQ_GET) && !checkheaders(data, "Range:")) { + /* if a line like this was already allocated, free the previous one */ + if(conn->allocptr.rangeline) + free(conn->allocptr.rangeline); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range); } else if((data->set.httpreq != HTTPREQ_GET) && @@ -705,7 +725,9 @@ CURLcode Curl_http(struct connectdata *conn) "%s" /* host */ "%s" /* pragma */ "%s" /* accept */ - "%s", /* referer */ + "%s" /* accept-encoding */ + "%s" /* referer */ + "%s",/* transfer-encoding */ data->set.customrequest?data->set.customrequest: (data->set.no_body?"HEAD": @@ -725,7 +747,10 @@ CURLcode Curl_http(struct connectdata *conn) (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */ http->p_pragma?http->p_pragma:"", http->p_accept?http->p_accept:"", - (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> <CRLF> */ + (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)? + conn->allocptr.accept_encoding:"", /* 08/28/02 jhrg */ + (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> <CRLF> */, + te ); if(co) { @@ -780,16 +805,16 @@ CURLcode Curl_http(struct connectdata *conn) strcpy(buf, "no strftime() support"); #endif switch(data->set.timecondition) { - case TIMECOND_IFMODSINCE: + case CURL_TIMECOND_IFMODSINCE: default: add_bufferf(req_buffer, "If-Modified-Since: %s\r\n", buf); break; - case TIMECOND_IFUNMODSINCE: + case CURL_TIMECOND_IFUNMODSINCE: add_bufferf(req_buffer, "If-Unmodified-Since: %s\r\n", buf); break; - case TIMECOND_LASTMOD: + case CURL_TIMECOND_LASTMOD: add_bufferf(req_buffer, "Last-Modified: %s\r\n", buf); break; @@ -814,7 +839,9 @@ CURLcode Curl_http(struct connectdata *conn) headers = headers->next; } - if(HTTPREQ_POST_FORM == data->set.httpreq) { + switch(data->set.httpreq) { + + case HTTPREQ_POST_FORM: if(Curl_FormInit(&http->form, http->sendit)) { failf(data, "Internal HTTP POST error!"); return CURLE_HTTP_POST_ERROR; @@ -883,9 +910,9 @@ CURLcode Curl_http(struct connectdata *conn) Curl_formclean(http->sendit); /* free that whole lot */ return result; } - } - else if(HTTPREQ_PUT == data->set.httpreq) { - /* Let's PUT the data to the server! */ + break; + + case HTTPREQ_PUT: /* Let's PUT the data to the server! */ if(data->set.infilesize>0) { add_bufferf(req_buffer, @@ -911,51 +938,53 @@ CURLcode Curl_http(struct connectdata *conn) &http->writebytecount); if(result) return result; - - } - else { - if(HTTPREQ_POST == data->set.httpreq) { - /* this is the simple POST, using x-www-form-urlencoded style */ - - if(!data->set.postfields) { - /* - * This is an attempt to do a POST without having anything to - * actually send. Let's make a NULL pointer equal "" here. Good/bad - * ? - */ - data->set.postfields = (char *)""; - data->set.postfieldsize = 0; /* it might been set to something illegal, - anything > 0 would be! */ - } + break; - if(!checkheaders(data, "Content-Length:")) - /* we allow replacing this header, although it isn't very wise to - actually set your own */ - add_bufferf(req_buffer, - "Content-Length: %d\r\n", - (data->set.postfieldsize?data->set.postfieldsize: - strlen(data->set.postfields)) ); + case HTTPREQ_POST: + /* this is the simple POST, using x-www-form-urlencoded style */ - if(!checkheaders(data, "Content-Type:")) - add_bufferf(req_buffer, - "Content-Type: application/x-www-form-urlencoded\r\n"); + if(!checkheaders(data, "Content-Length:")) + /* we allow replacing this header, although it isn't very wise to + actually set your own */ + add_bufferf(req_buffer, + "Content-Length: %d\r\n", + data->set.postfieldsize? + data->set.postfieldsize: + (data->set.postfields?strlen(data->set.postfields):0) ); - /* and here comes the actual data */ - if(data->set.postfieldsize) { - add_buffer(req_buffer, "\r\n", 2); - add_buffer(req_buffer, data->set.postfields, - data->set.postfieldsize); - } - else { - add_bufferf(req_buffer, - "\r\n" - "%s", - data->set.postfields ); - } + if(!checkheaders(data, "Content-Type:")) + add_bufferf(req_buffer, + "Content-Type: application/x-www-form-urlencoded\r\n"); + + add_buffer(req_buffer, "\r\n", 2); + + /* and here comes the actual data */ + if(data->set.postfieldsize && data->set.postfields) { + add_buffer(req_buffer, data->set.postfields, + data->set.postfieldsize); } + else if(data->set.postfields) + add_bufferf(req_buffer, + "%s", + data->set.postfields ); + + /* issue the request */ + result = add_buffer_send(conn->firstsocket, conn, req_buffer, + &data->info.request_size); + + if(result) + failf(data, "Failed sending HTTP POST request"); else - add_buffer(req_buffer, "\r\n", 2); + result = + Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + &http->readbytecount, + data->set.postfields?-1:conn->firstsocket, + data->set.postfields?NULL:&http->writebytecount); + break; + default: + add_buffer(req_buffer, "\r\n", 2); + /* issue the request */ result = add_buffer_send(conn->firstsocket, conn, req_buffer, &data->info.request_size); @@ -964,7 +993,8 @@ CURLcode Curl_http(struct connectdata *conn) failf(data, "Failed sending HTTP request"); else /* HTTP GET/HEAD download: */ - result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount, + result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, + &http->readbytecount, -1, NULL); /* nothing to upload */ } if(result) @@ -983,3 +1013,4 @@ CURLcode Curl_http(struct connectdata *conn) * vim600: fdm=marker * vim: et sw=2 ts=2 sts=2 tw=78 */ +#endif diff --git a/Source/CTest/Curl/http.h b/Source/CTest/Curl/http.h index abd96ba..d78322c 100644 --- a/Source/CTest/Curl/http.h +++ b/Source/CTest/Curl/http.h @@ -1,29 +1,29 @@ #ifndef __HTTP_H #define __HTTP_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ - + ***************************************************************************/ +#ifndef CURL_DISABLE_HTTP /* ftp can use this as well */ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, int tunnelsocket, @@ -38,5 +38,5 @@ CURLcode Curl_http_connect(struct connectdata *conn); void Curl_httpchunk_init(struct connectdata *conn); CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, ssize_t length, ssize_t *wrote); - +#endif #endif diff --git a/Source/CTest/Curl/http_chunks.c b/Source/CTest/Curl/http_chunks.c index 1754079..6d2a640 100644 --- a/Source/CTest/Curl/http_chunks.c +++ b/Source/CTest/Curl/http_chunks.c @@ -1,27 +1,28 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" +#ifndef CURL_DISABLE_HTTP /* -- WIN32 approved -- */ #include <stdio.h> #include <string.h> @@ -32,6 +33,8 @@ #include "urldata.h" /* it includes http_chunks.h */ #include "sendf.h" /* for the client write stuff */ +#include "content_encoding.h" /* 08/29/02 jhrg */ + #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -171,7 +174,32 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, piece = (ch->datasize >= length)?length:ch->datasize; /* Write the data portion available */ - result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap, piece); + /* Added content-encoding here; untested but almost identical to the + tested code in transfer.c. 08/29/02 jhrg */ +#ifdef HAVE_LIBZ + switch (conn->keep.content_encoding) { + case IDENTITY: +#endif + result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap, + piece); +#ifdef HAVE_LIBZ + break; + + case DEFLATE: + result = Curl_unencode_deflate_write(conn->data, &conn->keep, piece); + break; + + case GZIP: + case COMPRESS: + default: + failf (conn->data, + "Unrecognized content encoding type. " + "libcurl understands `identity' and `deflate' " + "content encodings."); + return CHUNKE_BAD_ENCODING; + } +#endif + if(result) return CHUNKE_WRITE_ERROR; *wrote += piece; @@ -228,3 +256,4 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, * vim600: fdm=marker * vim: et sw=2 ts=2 sts=2 tw=78 */ +#endif /* CURL_DISABLE_HTTP */ diff --git a/Source/CTest/Curl/http_chunks.h b/Source/CTest/Curl/http_chunks.h index c3e54a3..1b15d6c 100644 --- a/Source/CTest/Curl/http_chunks.h +++ b/Source/CTest/Curl/http_chunks.h @@ -1,27 +1,27 @@ #ifndef __HTTP_CHUNKS_H #define __HTTP_CHUNKS_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* * The longest possible hexadecimal number we support in a chunked transfer. * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() @@ -73,6 +73,7 @@ typedef enum { CHUNKE_BAD_CHUNK, CHUNKE_WRITE_ERROR, CHUNKE_STATE_ERROR, + CHUNKE_BAD_ENCODING, CHUNKE_LAST } CHUNKcode; diff --git a/Source/CTest/Curl/if2ip.c b/Source/CTest/Curl/if2ip.c index 0a63730..5f958d3 100644 --- a/Source/CTest/Curl/if2ip.c +++ b/Source/CTest/Curl/if2ip.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/if2ip.h b/Source/CTest/Curl/if2ip.h index 2fbb471..2be0ea5 100644 --- a/Source/CTest/Curl/if2ip.h +++ b/Source/CTest/Curl/if2ip.h @@ -1,27 +1,27 @@ #ifndef __IF2IP_H #define __IF2IP_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" #if ! defined(WIN32) && ! defined(__BEOS__) && !defined(__CYGWIN32__) diff --git a/Source/CTest/Curl/krb4.c b/Source/CTest/Curl/krb4.c index a182bea..ab38d30 100644 --- a/Source/CTest/Curl/krb4.c +++ b/Source/CTest/Curl/krb4.c @@ -40,6 +40,7 @@ #include "setup.h" +#ifndef CURL_DISABLE_FTP #ifdef KRB4 #include "security.h" @@ -197,7 +198,7 @@ krb4_auth(void *app_data, struct connectdata *conn) int checksum; u_int32_t cs; struct krb4_data *d = app_data; - char *host = conn->hostaddr->h_name; + char *host = conn->hostname; ssize_t nread; int l = sizeof(conn->local_addr); struct SessionHandle *data = conn->data; @@ -362,7 +363,7 @@ void Curl_krb_kauth(struct connectdata *conn) if (strcmp ((char*)tktcopy.dat + 8, KRB_TICKET_GRANTING_TICKET) != 0) { afs_string_to_key (passwd, - krb_realmofhost(conn->hostaddr->h_name), + krb_realmofhost(conn->hostname), &key); des_key_sched (&key, schedule); des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat, @@ -391,6 +392,7 @@ void Curl_krb_kauth(struct connectdata *conn) } #endif /* KRB4 */ +#endif /* CURL_DISABLE_FTP */ /* * local variables: diff --git a/Source/CTest/Curl/krb4.h b/Source/CTest/Curl/krb4.h index 6880486..8057058 100644 --- a/Source/CTest/Curl/krb4.h +++ b/Source/CTest/Curl/krb4.h @@ -1,27 +1,27 @@ #ifndef __KRB4_H #define __KRB4_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ void Curl_krb_kauth(struct connectdata *conn); #endif diff --git a/Source/CTest/Curl/ldap.c b/Source/CTest/Curl/ldap.c index 9080669..a1ef6fe 100644 --- a/Source/CTest/Curl/ldap.c +++ b/Source/CTest/Curl/ldap.c @@ -1,28 +1,29 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" +#ifndef CURL_DISABLE_LDAP /* -- WIN32 approved -- */ #include <stdio.h> #include <string.h> @@ -147,7 +148,7 @@ CURLcode Curl_ldap(struct connectdata *conn) int ldaptext; struct SessionHandle *data=conn->data; - infof(data, "LDAP: %s %s\n", data->change.url); + infof(data, "LDAP: %s\n", data->change.url); DynaOpen(); if (libldap == NULL) { @@ -229,3 +230,4 @@ CURLcode Curl_ldap(struct connectdata *conn) * vim600: fdm=marker * vim: et sw=2 ts=2 sts=2 tw=78 */ +#endif diff --git a/Source/CTest/Curl/ldap.h b/Source/CTest/Curl/ldap.h index c9ab7c8..2be32a8 100644 --- a/Source/CTest/Curl/ldap.h +++ b/Source/CTest/Curl/ldap.h @@ -1,29 +1,30 @@ #ifndef __LDAP_H #define __LDAP_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ +#ifndef CURL_DISABLE_LDAP CURLcode Curl_ldap(struct connectdata *conn); CURLcode Curl_ldap_done(struct connectdata *conn); - +#endif #endif /* __LDAP_H */ diff --git a/Source/CTest/Curl/llist.c b/Source/CTest/Curl/llist.c index 0d969ae..a9e65a8 100644 --- a/Source/CTest/Curl/llist.c +++ b/Source/CTest/Curl/llist.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -33,7 +33,7 @@ #include "memdebug.h" #endif void -curl_llist_init(curl_llist *l, curl_llist_dtor dtor) +Curl_llist_init(curl_llist *l, curl_llist_dtor dtor) { l->size = 0; l->dtor = dtor; @@ -42,7 +42,7 @@ curl_llist_init(curl_llist *l, curl_llist_dtor dtor) } curl_llist * -curl_llist_alloc(curl_llist_dtor dtor) +Curl_llist_alloc(curl_llist_dtor dtor) { curl_llist *list; @@ -50,13 +50,13 @@ curl_llist_alloc(curl_llist_dtor dtor) if(NULL == list) return NULL; - curl_llist_init(list, dtor); + Curl_llist_init(list, dtor); return list; } int -curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p) +Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p) { curl_llist_element *ne; @@ -84,7 +84,7 @@ curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p) } int -curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p) +Curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p) { curl_llist_element *ne; @@ -111,7 +111,7 @@ curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p) } int -curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user) +Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user) { if (e == NULL || list->size == 0) return 1; @@ -139,28 +139,28 @@ curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user) } int -curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user) +Curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user) { - return curl_llist_remove(list, e->next, user); + return Curl_llist_remove(list, e->next, user); } int -curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user) +Curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user) { - return curl_llist_remove(list, e->prev, user); + return Curl_llist_remove(list, e->prev, user); } size_t -curl_llist_count(curl_llist *list) +Curl_llist_count(curl_llist *list) { return list->size; } void -curl_llist_destroy(curl_llist *list, void *user) +Curl_llist_destroy(curl_llist *list, void *user) { while (list->size > 0) { - curl_llist_remove(list, CURL_LLIST_TAIL(list), user); + Curl_llist_remove(list, CURL_LLIST_TAIL(list), user); } free(list); diff --git a/Source/CTest/Curl/llist.h b/Source/CTest/Curl/llist.h index f598a1c..fa38e74 100644 --- a/Source/CTest/Curl/llist.h +++ b/Source/CTest/Curl/llist.h @@ -1,27 +1,27 @@ #ifndef __LLIST_H #define __LLIST_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" #include <stddef.h> @@ -44,14 +44,14 @@ typedef struct _curl_llist { size_t size; } curl_llist; -void curl_llist_init(curl_llist *, curl_llist_dtor); -curl_llist *curl_llist_alloc(curl_llist_dtor); -int curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *); -int curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *); -int curl_llist_remove(curl_llist *, curl_llist_element *, void *); -int curl_llist_remove_next(curl_llist *, curl_llist_element *, void *); -size_t curl_llist_count(curl_llist *); -void curl_llist_destroy(curl_llist *, void *); +void Curl_llist_init(curl_llist *, curl_llist_dtor); +curl_llist *Curl_llist_alloc(curl_llist_dtor); +int Curl_llist_insert_next(curl_llist *, curl_llist_element *, const void *); +int Curl_llist_insert_prev(curl_llist *, curl_llist_element *, const void *); +int Curl_llist_remove(curl_llist *, curl_llist_element *, void *); +int Curl_llist_remove_next(curl_llist *, curl_llist_element *, void *); +size_t Curl_llist_count(curl_llist *); +void Curl_llist_destroy(curl_llist *, void *); #define CURL_LLIST_HEAD(__l) ((__l)->head) #define CURL_LLIST_TAIL(__l) ((__l)->tail) diff --git a/Source/CTest/Curl/memdebug.c b/Source/CTest/Curl/memdebug.c index 9cb22d5..996aebb 100644 --- a/Source/CTest/Curl/memdebug.c +++ b/Source/CTest/Curl/memdebug.c @@ -1,26 +1,26 @@ #ifdef MALLOCDEBUG -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -49,7 +49,9 @@ struct memdebug { int size; - char mem[1]; + double mem[1]; + /* I'm hoping this is the thing with the strictest alignment + * requirements. That also means we waste some space :-( */ }; /* @@ -200,7 +202,15 @@ FILE *curl_fopen(const char *file, const char *mode, int curl_fclose(FILE *file, int line, const char *source) { - int res=(fclose)(file); + int res; + + if(NULL == file) { + fprintf(stderr, "ILLEGAL flose() on NULL at %s:%d\n", + source, line); + exit(2); + } + + res=(fclose)(file); if(logfile) fprintf(logfile, "FILE %s:%d fclose(%p)\n", source, line, file); diff --git a/Source/CTest/Curl/memdebug.h b/Source/CTest/Curl/memdebug.h index 3c5c090..3fa87ac 100644 --- a/Source/CTest/Curl/memdebug.h +++ b/Source/CTest/Curl/memdebug.h @@ -1,4 +1,26 @@ #ifdef MALLOCDEBUG +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ #include "setup.h" @@ -35,6 +57,7 @@ FILE *curl_fopen(const char *file, const char *mode, int line, int curl_fclose(FILE *file, int line, const char *source); /* Set this symbol on the command-line, recompile all lib-sources */ +#undef strdup #define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) #define malloc(size) curl_domalloc(size, __LINE__, __FILE__) #define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__) diff --git a/Source/CTest/Curl/mprintf.c b/Source/CTest/Curl/mprintf.c index b039d8d..4d3630a 100644 --- a/Source/CTest/Curl/mprintf.c +++ b/Source/CTest/Curl/mprintf.c @@ -1028,7 +1028,6 @@ static int alloc_addbyter(int output, FILE *data) infop->len++; return output; /* fputc() returns like this on success */ - } char *curl_maprintf(const char *format, ...) @@ -1044,12 +1043,17 @@ char *curl_maprintf(const char *format, ...) va_start(ap_save, format); retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); va_end(ap_save); - if(info.len) { + if(-1 == retcode) { + if(info.alloc) + free(info.buffer); + return NULL; + } + if(info.alloc) { info.buffer[info.len] = 0; /* we terminate this with a zero byte */ return info.buffer; } else - return NULL; + return strdup(""); } char *curl_mvaprintf(const char *format, va_list ap_save) @@ -1062,13 +1066,18 @@ char *curl_mvaprintf(const char *format, va_list ap_save) info.alloc = 0; retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); - info.buffer[info.len] = 0; /* we terminate this with a zero byte */ - if(info.len) { + if(-1 == retcode) { + if(info.alloc) + free(info.buffer); + return NULL; + } + + if(info.alloc) { info.buffer[info.len] = 0; /* we terminate this with a zero byte */ return info.buffer; } else - return NULL; + return strdup(""); } static int storebuffer(int output, FILE *data) diff --git a/Source/CTest/Curl/multi.c b/Source/CTest/Curl/multi.c index bfd3949..f901f3a 100644 --- a/Source/CTest/Curl/multi.c +++ b/Source/CTest/Curl/multi.c @@ -1,36 +1,40 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" #include <stdlib.h> #include <string.h> #include <curl/curl.h> -#include "multi.h" /* will become <curl/multi.h> soon */ - #include "urldata.h" #include "transfer.h" #include "url.h" +#include "connect.h" + +/* The last #include file should be: */ +#ifdef MALLOCDEBUG +#include "memdebug.h" +#endif struct Curl_message { /* the 'CURLMsg' is the part that is visible to the external user */ @@ -40,11 +44,13 @@ struct Curl_message { typedef enum { CURLM_STATE_INIT, - CURLM_STATE_CONNECT, - CURLM_STATE_DO, - CURLM_STATE_PERFORM, - CURLM_STATE_DONE, - CURLM_STATE_COMPLETED, + CURLM_STATE_CONNECT, /* connect has been sent off */ + CURLM_STATE_WAITCONNECT, /* we're awaiting the connect to finalize */ + CURLM_STATE_DO, /* send off the request (part 1) */ + CURLM_STATE_DO_MORE, /* send off the request (part 2) */ + CURLM_STATE_PERFORM, /* transfer data */ + CURLM_STATE_DONE, /* post data transfer operation */ + CURLM_STATE_COMPLETED, /* operation complete */ CURLM_STATE_LAST /* not a true state, never use this */ } CURLMstate; @@ -59,6 +65,13 @@ struct Curl_one_easy { CURLMstate state; /* the handle's state */ CURLcode result; /* previous result */ + + struct Curl_message *msg; /* A pointer to one single posted message. + Cleanup should be done on this pointer NOT on + the linked list in Curl_multi. This message + will be deleted when this handle is removed + from the multi-handle */ + int msg_num; /* number of messages left in 'msg' to return */ }; @@ -78,10 +91,8 @@ struct Curl_multi { /* This is the amount of entries in the linked list above. */ int num_easy; - /* this is a linked list of posted messages */ - struct Curl_message *msgs; - /* amount of messages in the queue */ - int num_msgs; + int num_msgs; /* total amount of messages in the easy handles */ + /* Hostname cache */ curl_hash *hostcache; }; @@ -171,6 +182,9 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle, /* If the 'state' is not INIT or COMPLETED, we might need to do something nice to put the easy_handle in a good known state when this returns. */ + /* clear out the usage of the shared DNS cache */ + easy->easy_handle->hostcache = NULL; + /* make the previous node point to our next */ if(easy->prev) easy->prev->next = easy->next; @@ -180,6 +194,8 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle, /* NOTE NOTE NOTE We do not touch the easy handle here! */ + if (easy->msg) + free(easy->msg); free(easy); multi->num_easy--; /* one less to care about now */ @@ -211,6 +227,32 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle, switch(easy->state) { default: break; + case CURLM_STATE_WAITCONNECT: + case CURLM_STATE_DO_MORE: + { + /* when we're waiting for a connect, we wait for the socket to + become writable */ + struct connectdata *conn = easy->easy_conn; + int sockfd; + + if(CURLM_STATE_WAITCONNECT == easy->state) { + sockfd = conn->firstsocket; + FD_SET(sockfd, write_fd_set); + } + else { + /* When in DO_MORE state, we could be either waiting for us + to connect to a remote site, or we could wait for that site + to connect to us. It makes a difference in the way: if we + connect to the site we wait for the socket to become writable, if + the site connects to us we wait for it to become readable */ + sockfd = conn->secondarysocket; + FD_SET(sockfd, write_fd_set); + } + + if(sockfd > *max_fd) + *max_fd = sockfd; + } + break; case CURLM_STATE_PERFORM: /* This should have a set of file descriptors for us to set. */ /* after the transfer is done, go DONE */ @@ -237,6 +279,8 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) struct Curl_one_easy *easy; bool done; CURLMcode result=CURLM_OK; + struct Curl_message *msg = NULL; + bool connected; *running_handles = 0; /* bump this once for every living handle */ @@ -245,14 +289,23 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) easy=multi->easy.next; while(easy) { + +#ifdef MALLOCDEBUG + fprintf(stderr, "HANDLE %p: State: %x\n", + (char *)easy, easy->state); +#endif + switch(easy->state) { case CURLM_STATE_INIT: /* init this transfer. */ easy->result=Curl_pretransfer(easy->easy_handle); + if(CURLE_OK == easy->result) { /* after init, go CONNECT */ easy->state = CURLM_STATE_CONNECT; result = CURLM_CALL_MULTI_PERFORM; + + easy->easy_handle->state.used_interface = Curl_if_multi; } break; case CURLM_STATE_CONNECT: @@ -261,7 +314,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) } else { if (multi->hostcache == NULL) { - multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo); + multi->hostcache = Curl_hash_alloc(7, Curl_freeaddrinfo); } easy->easy_handle->hostcache = multi->hostcache; @@ -270,43 +323,133 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) /* Connect. We get a connection identifier filled in. */ easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn); - /* after connect, go DO */ + /* after the connect has been sent off, go WAITCONNECT */ if(CURLE_OK == easy->result) { - easy->state = CURLM_STATE_DO; + easy->state = CURLM_STATE_WAITCONNECT; result = CURLM_CALL_MULTI_PERFORM; } break; + + case CURLM_STATE_WAITCONNECT: + { + bool connected; + easy->result = Curl_is_connected(easy->easy_conn, + easy->easy_conn->firstsocket, + &connected); + if(connected) + easy->result = Curl_protocol_connect(easy->easy_conn, NULL); + + if(CURLE_OK != easy->result) { + /* failure detected */ + Curl_disconnect(easy->easy_conn); /* close the connection */ + easy->easy_conn = NULL; /* no more connection */ + break; + } + + if(connected) { + /* after the connect has completed, go DO */ + easy->state = CURLM_STATE_DO; + result = CURLM_CALL_MULTI_PERFORM; + } + } + break; + case CURLM_STATE_DO: /* Do the fetch or put request */ easy->result = Curl_do(&easy->easy_conn); - /* after do, go PERFORM */ if(CURLE_OK == easy->result) { - if(CURLE_OK == Curl_readwrite_init(easy->easy_conn)) { + + /* after do, go PERFORM... or DO_MORE */ + if(easy->easy_conn->bits.do_more) { + /* we're supposed to do more, but we need to sit down, relax + and wait a little while first */ + easy->state = CURLM_STATE_DO_MORE; + result = CURLM_OK; + } + else { + /* we're done with the DO, now PERFORM */ + easy->result = Curl_readwrite_init(easy->easy_conn); + if(CURLE_OK == easy->result) { + easy->state = CURLM_STATE_PERFORM; + result = CURLM_CALL_MULTI_PERFORM; + } + } + } + break; + + case CURLM_STATE_DO_MORE: + /* + * First, check if we really are ready to do more. + */ + easy->result = Curl_is_connected(easy->easy_conn, + easy->easy_conn->secondarysocket, + &connected); + if(connected) { + /* + * When we are connected, DO MORE and then go PERFORM + */ + easy->result = Curl_do_more(easy->easy_conn); + + if(CURLE_OK == easy->result) + easy->result = Curl_readwrite_init(easy->easy_conn); + + if(CURLE_OK == easy->result) { easy->state = CURLM_STATE_PERFORM; result = CURLM_CALL_MULTI_PERFORM; } } break; + case CURLM_STATE_PERFORM: /* read/write data if it is ready to do so */ easy->result = Curl_readwrite(easy->easy_conn, &done); - /* hm, when we follow redirects, we may need to go back to the CONNECT - state */ + + if(easy->result) { + /* The transfer phase returned error, we mark the connection to get + * closed to prevent being re-used. This is becasue we can't + * possibly know if the connection is in a good shape or not now. */ + easy->easy_conn->bits.close = TRUE; + + if(-1 !=easy->easy_conn->secondarysocket) { + /* if we failed anywhere, we must clean up the secondary socket if + it was used */ + sclose(easy->easy_conn->secondarysocket); + easy->easy_conn->secondarysocket=-1; + } + Curl_posttransfer(easy->easy_handle); + Curl_done(easy->easy_conn); + } + /* after the transfer is done, go DONE */ - if(TRUE == done) { + else if(TRUE == done) { + /* call this even if the readwrite function returned error */ - easy->result = Curl_posttransfer(easy->easy_handle); - easy->state = CURLM_STATE_DONE; - result = CURLM_CALL_MULTI_PERFORM; + Curl_posttransfer(easy->easy_handle); + + /* When we follow redirects, must to go back to the CONNECT state */ + if(easy->easy_conn->newurl) { + easy->result = Curl_follow(easy->easy_handle, + strdup(easy->easy_conn->newurl)); + if(CURLE_OK == easy->result) { + easy->state = CURLM_STATE_CONNECT; + result = CURLM_CALL_MULTI_PERFORM; + } + } + else { + easy->state = CURLM_STATE_DONE; + result = CURLM_CALL_MULTI_PERFORM; + } } break; case CURLM_STATE_DONE: /* post-transfer command */ easy->result = Curl_done(easy->easy_conn); - /* after we have DONE what we're supposed to do, go COMPLETED */ - if(CURLE_OK == easy->result) - easy->state = CURLM_STATE_COMPLETED; + + /* after we have DONE what we're supposed to do, go COMPLETED, and + it doesn't matter what the Curl_done() returned! */ + easy->state = CURLM_STATE_COMPLETED; break; + case CURLM_STATE_COMPLETED: /* this is a completed transfer, it is likely to still be connected */ @@ -317,30 +460,66 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) return CURLM_INTERNAL_ERROR; } - if((CURLM_STATE_COMPLETED != easy->state) && - (CURLE_OK != easy->result)) { - /* - * If an error was returned, and we aren't in completed now, - * then we go to completed and consider this transfer aborted. - */ - easy->state = CURLM_STATE_COMPLETED; + if(CURLM_STATE_COMPLETED != easy->state) { + if(CURLE_OK != easy->result) + /* + * If an error was returned, and we aren't in completed state now, + * then we go to completed and consider this transfer aborted. */ + easy->state = CURLM_STATE_COMPLETED; + else + /* this one still lives! */ + (*running_handles)++; + } + + if ((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) { + /* clear out the usage of the shared DNS cache */ + easy->easy_handle->hostcache = NULL; + + /* now add a node to the Curl_message linked list with this info */ + msg = (struct Curl_message *)malloc(sizeof(struct Curl_message)); + + if(!msg) + return CURLM_OUT_OF_MEMORY; + + msg->extmsg.msg = CURLMSG_DONE; + msg->extmsg.easy_handle = easy->easy_handle; + msg->extmsg.data.result = easy->result; + msg->next=NULL; + + easy->msg = msg; + easy->msg_num = 1; /* there is one unread message here */ + + multi->num_msgs++; /* increase message counter */ } - else if(CURLM_STATE_COMPLETED != easy->state) - /* this one still lives! */ - (*running_handles)++; easy = easy->next; /* operate on next handle */ } + return result; } CURLMcode curl_multi_cleanup(CURLM *multi_handle) { struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + struct Curl_one_easy *easy; + struct Curl_one_easy *nexteasy; + if(GOOD_MULTI_HANDLE(multi)) { multi->type = 0; /* not good anymore */ - curl_hash_destroy(multi->hostcache); + Curl_hash_destroy(multi->hostcache); + /* remove all easy handles */ + easy = multi->easy.next; + while(easy) { + nexteasy=easy->next; + /* clear out the usage of the shared DNS cache */ + easy->easy_handle->hostcache = NULL; + + if (easy->msg) + free(easy->msg); + free(easy); + easy = nexteasy; + } free(multi); @@ -350,7 +529,35 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle) return CURLM_BAD_HANDLE; } -CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue); +CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue) +{ + struct Curl_multi *multi=(struct Curl_multi *)multi_handle; + + if(GOOD_MULTI_HANDLE(multi)) { + struct Curl_one_easy *easy; + + if(!multi->num_msgs) + return NULL; /* no messages left to return */ + + easy=multi->easy.next; + while(easy) { + if(easy->msg_num) { + easy->msg_num--; + break; + } + easy = easy->next; + } + if(!easy) + return NULL; /* this means internal count confusion really */ + + multi->num_msgs--; + *msgs_in_queue = multi->num_msgs; + + return &easy->msg->extmsg; + } + else + return NULL; +} /* * local variables: diff --git a/Source/CTest/Curl/netrc.c b/Source/CTest/Curl/netrc.c index c2c8e65..a2d6708 100644 --- a/Source/CTest/Curl/netrc.c +++ b/Source/CTest/Curl/netrc.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -78,12 +78,15 @@ int Curl_parsenetrc(char *host, FILE *file; char netrcbuffer[256]; int retcode=1; + + int specific_login = (login[0] != 0); char *home = NULL; int state=NOTHING; - char state_login=0; - char state_password=0; + char state_login=0; /* Found a login keyword */ + char state_password=0; /* Found a password keyword */ + char state_our_login=0; /* With specific_login, found *our* login name */ #define NETRC DOT_CHAR "netrc" @@ -116,6 +119,30 @@ int Curl_parsenetrc(char *host, sprintf(netrcbuffer, "%s%s%s", home, DIR_CHAR, NETRC); +#ifdef MALLOCDEBUG + { + /* This is a hack to allow testing. + * If compiled with --enable-debug and CURL_DEBUG_NETRC is defined, + * then it's the path to a substitute .netrc for testing purposes *only* */ + + char *override = curl_getenv("CURL_DEBUG_NETRC"); + + if (override != NULL) { + printf("NETRC: overridden .netrc file: %s\n", home); + + if (strlen(override)+1 > sizeof(netrcbuffer)) { + free(override); + if(NULL==pw) + free(home); + + return -1; + } + strcpy(netrcbuffer, override); + free(override); + } + } +#endif /* MALLOCDEBUG */ + file = fopen(netrcbuffer, "r"); if(file) { char *tok; @@ -123,6 +150,10 @@ int Curl_parsenetrc(char *host, while(fgets(netrcbuffer, sizeof(netrcbuffer), file)) { tok=strtok_r(netrcbuffer, " \t\n", &tok_buf); while(tok) { + + if (login[0] && password[0]) + goto done; + switch(state) { case NOTHING: if(strequal("machine", tok)) { @@ -149,17 +180,23 @@ int Curl_parsenetrc(char *host, case HOSTVALID: /* we are now parsing sub-keywords concerning "our" host */ if(state_login) { - strncpy(login, tok, LOGINSIZE-1); + if (specific_login) { + state_our_login = strequal(login, tok); + }else{ + strncpy(login, tok, LOGINSIZE-1); #ifdef _NETRC_DEBUG - printf("LOGIN: %s\n", login); + printf("LOGIN: %s\n", login); #endif + } state_login=0; } else if(state_password) { - strncpy(password, tok, PASSWORDSIZE-1); + if (state_our_login || !specific_login) { + strncpy(password, tok, PASSWORDSIZE-1); #ifdef _NETRC_DEBUG - printf("PASSWORD: %s\n", password); + printf("PASSWORD: %s\n", password); #endif + } state_password=0; } else if(strequal("login", tok)) @@ -169,13 +206,16 @@ int Curl_parsenetrc(char *host, else if(strequal("machine", tok)) { /* ok, there's machine here go => */ state = HOSTFOUND; + state_our_login = 0; } break; } /* switch (state) */ + tok = strtok_r(NULL, " \t\n", &tok_buf); } /* while (tok) */ } /* while fgets() */ +done: fclose(file); } diff --git a/Source/CTest/Curl/netrc.h b/Source/CTest/Curl/netrc.h index de95390..bbafb3d 100644 --- a/Source/CTest/Curl/netrc.h +++ b/Source/CTest/Curl/netrc.h @@ -1,28 +1,33 @@ #ifndef __NETRC_H #define __NETRC_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ int Curl_parsenetrc(char *host, char *login, char *password); + /* Assume: password[0]=0, host[0] != 0. + * If login[0] = 0, search for login and password within a machine section + * in the netrc. + * If login[0] != 0, search for password within machine and login. + */ #endif diff --git a/Source/CTest/Curl/progress.c b/Source/CTest/Curl/progress.c index 318a6d8..76fa18c 100644 --- a/Source/CTest/Curl/progress.c +++ b/Source/CTest/Curl/progress.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -45,6 +45,10 @@ #include "progress.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include <curl/mprintf.h> + + static void time2str(char *r, int t) { int h = (t/3600); @@ -103,6 +107,15 @@ void Curl_pgrsDone(struct connectdata *conn) } } +/* reset all times except redirect */ +void Curl_pgrsResetTimes(struct SessionHandle *data) +{ + data->progress.t_nslookup = 0.0; + data->progress.t_connect = 0.0; + data->progress.t_pretransfer = 0.0; + data->progress.t_starttransfer = 0.0; +} + void Curl_pgrsTime(struct SessionHandle *data, timerid timer) { switch(timer) { @@ -134,6 +147,10 @@ void Curl_pgrsTime(struct SessionHandle *data, timerid timer) case TIMER_POSTRANSFER: /* this is the normal end-of-transfer thing */ break; + case TIMER_REDIRECT: + data->progress.t_redirect = + (double)Curl_tvdiff(Curl_tvnow(), data->progress.start)/1000.0; + break; } } @@ -327,8 +344,8 @@ int Curl_pgrsUpdate(struct connectdata *conn) /* If we have a total estimate, we can display that and the expected time left */ if(total_estimate) { - time2str(time_left, total_estimate-(int) data->progress.timespent); - time2str(time_total, total_estimate); + time2str(time_left, (int)(total_estimate - data->progress.timespent)); + time2str(time_total, (int)total_estimate); } else { /* otherwise we blank those times */ @@ -336,7 +353,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) strcpy(time_total, "--:--:--"); } /* The time spent so far is always known */ - time2str(time_current, data->progress.timespent); + time2str(time_current, (int)data->progress.timespent); /* Get the total amount of data expected to get transfered */ total_expected_transfer = diff --git a/Source/CTest/Curl/progress.h b/Source/CTest/Curl/progress.h index 2d45984..51994cb 100644 --- a/Source/CTest/Curl/progress.h +++ b/Source/CTest/Curl/progress.h @@ -1,27 +1,27 @@ #ifndef __PROGRESS_H #define __PROGRESS_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "timeval.h" @@ -34,6 +34,7 @@ typedef enum { TIMER_STARTTRANSFER, TIMER_POSTRANSFER, TIMER_STARTSINGLE, + TIMER_REDIRECT, TIMER_LAST /* must be last */ } timerid; @@ -44,6 +45,7 @@ void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size); void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, double size); void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size); int Curl_pgrsUpdate(struct connectdata *); +void Curl_pgrsResetTimes(struct SessionHandle *data); void Curl_pgrsTime(struct SessionHandle *data, timerid timer); diff --git a/Source/CTest/Curl/security.c b/Source/CTest/Curl/security.c index 9e2cc2e..aa11a8f 100644 --- a/Source/CTest/Curl/security.c +++ b/Source/CTest/Curl/security.c @@ -40,6 +40,7 @@ #include "setup.h" +#ifndef CURL_DISABLE_FTP #ifdef KRB4 #define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */ @@ -552,6 +553,7 @@ Curl_sec_end(struct connectdata *conn) } #endif /* KRB4 */ +#endif /* CURL_DISABLE_FTP */ /* * local variables: diff --git a/Source/CTest/Curl/security.h b/Source/CTest/Curl/security.h index cd8d235..3bbb78f 100644 --- a/Source/CTest/Curl/security.h +++ b/Source/CTest/Curl/security.h @@ -1,27 +1,27 @@ #ifndef __SECURITY_H #define __SECURITY_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* this is a re-write */ diff --git a/Source/CTest/Curl/sendf.c b/Source/CTest/Curl/sendf.c index 7f203ee..6ebe014 100644 --- a/Source/CTest/Curl/sendf.c +++ b/Source/CTest/Curl/sendf.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -62,18 +62,18 @@ /* returns last node in linked list */ static struct curl_slist *slist_get_last(struct curl_slist *list) { - struct curl_slist *item; - - /* if caller passed us a NULL, return now */ - if (!list) - return NULL; - - /* loop through to find the last item */ - item = list; - while (item->next) { - item = item->next; - } - return item; + struct curl_slist *item; + + /* if caller passed us a NULL, return now */ + if (!list) + return NULL; + + /* loop through to find the last item */ + item = list; + while (item->next) { + item = item->next; + } + return item; } /* append a struct to the linked list. It always retunrs the address of the @@ -84,61 +84,61 @@ static struct curl_slist *slist_get_last(struct curl_slist *list) struct curl_slist *curl_slist_append(struct curl_slist *list, const char *data) { - struct curl_slist *last; - struct curl_slist *new_item; - - new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist)); - if (new_item) { - new_item->next = NULL; - new_item->data = strdup(data); - } - else { - fprintf(stderr, "Cannot allocate memory for QUOTE list.\n"); - return NULL; - } - - if (list) { - last = slist_get_last(list); - last->next = new_item; - return list; - } - - /* if this is the first item, then new_item *is* the list */ - return new_item; + struct curl_slist *last; + struct curl_slist *new_item; + + new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist)); + if (new_item) { + new_item->next = NULL; + new_item->data = strdup(data); + } + if (new_item == NULL || new_item->data == NULL) { + fprintf(stderr, "Cannot allocate memory for QUOTE list.\n"); + return NULL; + } + + if (list) { + last = slist_get_last(list); + last->next = new_item; + return list; + } + + /* if this is the first item, then new_item *is* the list */ + return new_item; } /* be nice and clean up resources */ void curl_slist_free_all(struct curl_slist *list) { - struct curl_slist *next; - struct curl_slist *item; + struct curl_slist *next; + struct curl_slist *item; - if (!list) - return; + if (!list) + return; - item = list; - do { - next = item->next; + item = list; + do { + next = item->next; - if (item->data) { - free(item->data); - } - free(item); - item = next; - } while (next); + if (item->data) { + free(item->data); + } + free(item); + item = next; + } while (next); } - /* Curl_infof() is for info message along the way */ void Curl_infof(struct SessionHandle *data, const char *fmt, ...) { va_list ap; if(data->set.verbose) { + char print_buffer[1024 + 1]; va_start(ap, fmt); - fputs("* ", data->set.err); - vfprintf(data->set.err, fmt, ap); + vsnprintf(print_buffer, 1024, fmt, ap); va_end(ap); + Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer)); } } @@ -153,6 +153,10 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...) if(data->set.errorbuffer && !data->state.errorbuf) { vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap); data->state.errorbuf = TRUE; /* wrote error string */ + + if(data->set.verbose) + Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, + strlen(data->set.errorbuffer)); } va_end(ap); } @@ -163,23 +167,45 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn, { struct SessionHandle *data = conn->data; ssize_t bytes_written; - CURLcode result; + ssize_t write_len; + CURLcode res; char *s; + char *sptr; va_list ap; va_start(ap, fmt); s = vaprintf(fmt, ap); /* returns an allocated string */ va_end(ap); if(!s) - return 0; /* failure */ - if(data->set.verbose) - fprintf(data->set.err, "> %s", s); + return CURLE_OUT_OF_MEMORY; /* failure */ - /* Write the buffer to the socket */ - result = Curl_write(conn, sockfd, s, strlen(s), &bytes_written); + bytes_written=0; + write_len = strlen(s); + sptr = s; + + do { + /* Write the buffer to the socket */ + res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written); + + if(CURLE_OK != res) + break; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written); + + if(bytes_written != write_len) { + /* if not all was written at once, we must advance the pointer, decrease + the size left and try again! */ + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + + } while(1); free(s); /* free the output string */ - return result; + return res; } /* @@ -212,7 +238,7 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd, } /* a true error */ failf(conn->data, "SSL_write() return error %d\n", err); - return CURLE_WRITE_ERROR; + return CURLE_SEND_ERROR; } bytes_written = rc; } @@ -244,7 +270,7 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd, #endif *written = bytes_written; - return (-1 != bytes_written)?CURLE_OK:CURLE_WRITE_ERROR; + return (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR; } /* client_write() sends data to the write callback(s) @@ -325,6 +351,9 @@ int Curl_read(struct connectdata *conn, case SSL_ERROR_WANT_WRITE: /* if there's data pending, then we re-invoke SSL_read() */ break; + default: + failf(conn->data, "SSL read error: %d", err); + return CURLE_RECV_ERROR; } } while(loop); if(loop && SSL_pending(conn->ssl.handle)) @@ -355,6 +384,29 @@ int Curl_read(struct connectdata *conn, return CURLE_OK; } +/* return 0 on success */ +int Curl_debug(struct SessionHandle *data, curl_infotype type, + char *ptr, size_t size) +{ + static const char * const s_infotype[CURLINFO_END] = { + "* ", "< ", "> ", "{ ", "} " }; + + if(data->set.fdebug) + return (*data->set.fdebug)(data, type, ptr, size, + data->set.debugdata); + + switch(type) { + case CURLINFO_TEXT: + case CURLINFO_HEADER_OUT: + fwrite(s_infotype[type], 2, 1, data->set.err); + fwrite(ptr, size, 1, data->set.err); + break; + default: /* nada */ + break; + } + return 0; +} + /* * local variables: diff --git a/Source/CTest/Curl/sendf.h b/Source/CTest/Curl/sendf.h index 6724810..665a4c8 100644 --- a/Source/CTest/Curl/sendf.h +++ b/Source/CTest/Curl/sendf.h @@ -1,27 +1,27 @@ #ifndef __SENDF_H #define __SENDF_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ CURLcode Curl_sendf(int fd, struct connectdata *, const char *fmt, ...); void Curl_infof(struct SessionHandle *, const char *fmt, ...); @@ -53,4 +53,9 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd, void *mem, size_t len, ssize_t *written); +/* the function used to output verbose information */ +int Curl_debug(struct SessionHandle *handle, curl_infotype type, + char *data, size_t size); + + #endif diff --git a/Source/CTest/Curl/setup.h b/Source/CTest/Curl/setup.h index b18bae5..783fb83 100644 --- a/Source/CTest/Curl/setup.h +++ b/Source/CTest/Curl/setup.h @@ -1,29 +1,39 @@ #ifndef __SETUP_H #define __SETUP_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ - - + ***************************************************************************/ + +/* MN 06/07/02 */ +/* #define HTTP_ONLY +*/ +#ifdef HTTP_ONLY +#define CURL_DISABLE_FTP +#define CURL_DISABLE_LDAP +#define CURL_DISABLE_TELNET +#define CURL_DISABLE_DICT +#define CURL_DISABLE_FILE +#define CURL_DISABLE_GOPHER +#endif #if !defined(WIN32) && defined(_WIN32) /* This _might_ be a good Borland fix. Please report whether this works or diff --git a/Source/CTest/Curl/speedcheck.c b/Source/CTest/Curl/speedcheck.c index dbd2e87..5b4d018 100644 --- a/Source/CTest/Curl/speedcheck.c +++ b/Source/CTest/Curl/speedcheck.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/speedcheck.h b/Source/CTest/Curl/speedcheck.h index 08eca0d..e5397d2 100644 --- a/Source/CTest/Curl/speedcheck.h +++ b/Source/CTest/Curl/speedcheck.h @@ -1,27 +1,27 @@ #ifndef __SPEEDCHECK_H #define __SPEEDCHECK_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/ssluse.c b/Source/CTest/Curl/ssluse.c index 74cdca1..d3162f7 100644 --- a/Source/CTest/Curl/ssluse.c +++ b/Source/CTest/Curl/ssluse.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* * The original SSL code for curl was written by @@ -55,6 +55,15 @@ #undef HAVE_USERDATA_IN_PWD_CALLBACK #endif +#if OPENSSL_VERSION_NUMBER >= 0x00907001L +/* ENGINE_load_private_key() takes four arguments */ +#define HAVE_ENGINE_LOAD_FOUR_ARGS +#else +/* ENGINE_load_private_key() takes three arguments */ +#undef HAVE_ENGINE_LOAD_FOUR_ARGS +#endif + + #ifndef HAVE_USERDATA_IN_PWD_CALLBACK static char global_passwd[64]; #endif @@ -223,30 +232,22 @@ int cert_stuff(struct connectdata *conn, SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback); } -#if 0 - if (SSL_CTX_use_certificate_file(conn->ssl.ctx, - cert_file, - SSL_FILETYPE_PEM) != 1) { - failf(data, "unable to set certificate file (wrong password?)"); - return(0); - } - if (key_file == NULL) - key_file=cert_file; - - if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, - key_file, - SSL_FILETYPE_PEM) != 1) { - failf(data, "unable to set public key file"); - return(0); - } -#else - /* The '#ifdef 0' section above was removed on 17-dec-2001 */ - file_type = do_file_type(cert_type); switch(file_type) { case SSL_FILETYPE_PEM: + /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ + if (SSL_CTX_use_certificate_chain_file(conn->ssl.ctx, + cert_file) != 1) { + failf(data, "unable to set certificate file (wrong password?)"); + return 0; + } + break; + case SSL_FILETYPE_ASN1: + /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but + we use the case above for PEM so this can only be performed with + ASN1 files. */ if (SSL_CTX_use_certificate_file(conn->ssl.ctx, cert_file, file_type) != 1) { @@ -283,11 +284,17 @@ int cert_stuff(struct connectdata *conn, { /* XXXX still needs some work */ EVP_PKEY *priv_key = NULL; if (conn && conn->data && conn->data->engine) { +#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS + UI_METHOD *ui_method = UI_OpenSSL(); +#endif if (!key_file || !key_file[0]) { failf(data, "no key set to load from crypto engine\n"); return 0; } priv_key = ENGINE_load_private_key(conn->data->engine,key_file, +#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS + ui_method, +#endif data->set.key_passwd); if (!priv_key) { failf(data, "failed to load private key from crypto engine\n"); @@ -315,8 +322,6 @@ int cert_stuff(struct connectdata *conn, return 0; } -#endif - ssl=SSL_new(conn->ssl.ctx); x509=SSL_get_certificate(ssl); @@ -717,7 +722,7 @@ Curl_SSLConnect(struct connectdata *conn) data->set.key, data->set.key_type)) { /* failf() is already done in cert_stuff() */ - return CURLE_SSL_CONNECT_ERROR; + return CURLE_SSL_CERTPROBLEM; } } @@ -725,7 +730,7 @@ Curl_SSLConnect(struct connectdata *conn) if (!SSL_CTX_set_cipher_list(conn->ssl.ctx, data->set.ssl.cipher_list)) { failf(data, "failed setting cipher list"); - return CURLE_SSL_CONNECT_ERROR; + return CURLE_SSL_CIPHER; } } @@ -734,11 +739,12 @@ Curl_SSLConnect(struct connectdata *conn) SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_CLIENT_ONCE, cert_verify_callback); - if (!SSL_CTX_load_verify_locations(conn->ssl.ctx, + if ((data->set.ssl.CAfile || data->set.ssl.CApath) && + !SSL_CTX_load_verify_locations(conn->ssl.ctx, data->set.ssl.CAfile, data->set.ssl.CApath)) { failf(data,"error setting cerficate verify locations"); - return CURLE_SSL_CONNECT_ERROR; + return CURLE_SSL_CACERT; } } else diff --git a/Source/CTest/Curl/ssluse.h b/Source/CTest/Curl/ssluse.h index e8115f0..b8526a3 100644 --- a/Source/CTest/Curl/ssluse.h +++ b/Source/CTest/Curl/ssluse.h @@ -1,27 +1,27 @@ #ifndef __SSLUSE_H #define __SSLUSE_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "urldata.h" CURLcode Curl_SSLConnect(struct connectdata *conn); diff --git a/Source/CTest/Curl/strequal.c b/Source/CTest/Curl/strequal.c index 07bc16b..500e749 100644 --- a/Source/CTest/Curl/strequal.c +++ b/Source/CTest/Curl/strequal.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/strequal.h b/Source/CTest/Curl/strequal.h index e376db9..e63dc21 100644 --- a/Source/CTest/Curl/strequal.h +++ b/Source/CTest/Curl/strequal.h @@ -1,27 +1,27 @@ #ifndef __STREQUAL_H #define __STREQUAL_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* * These two actually are public functions. @@ -32,6 +32,10 @@ int curl_strnequal(const char *first, const char *second, size_t max); #define strequal(a,b) curl_strequal(a,b) #define strnequal(a,b,c) curl_strnequal(a,b,c) +/* checkprefix() is a shorter version of the above, used when the first + argument is zero-byte terminated */ +#define checkprefix(a,b) strnequal(a,b,strlen(a)) + #ifndef HAVE_STRLCAT #define strlcat(x,y,z) Curl_strlcat(x,y,z) size_t Curl_strlcat(char *dst, const char *src, size_t siz); diff --git a/Source/CTest/Curl/strtok.c b/Source/CTest/Curl/strtok.c index e7724d9..42ac1d8 100644 --- a/Source/CTest/Curl/strtok.c +++ b/Source/CTest/Curl/strtok.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/strtok.h b/Source/CTest/Curl/strtok.h index 6e7e167..242319a 100644 --- a/Source/CTest/Curl/strtok.h +++ b/Source/CTest/Curl/strtok.h @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #ifndef _CURL_STRTOK_R_H #define _CURL_STRTOK_R_H diff --git a/Source/CTest/Curl/telnet.c b/Source/CTest/Curl/telnet.c index 29c2110..42a1780 100644 --- a/Source/CTest/Curl/telnet.c +++ b/Source/CTest/Curl/telnet.c @@ -1,28 +1,29 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" +#ifndef CURL_DISABLE_TELNET /* -- WIN32 approved -- */ #include <stdio.h> #include <string.h> @@ -1049,6 +1050,7 @@ CURLcode Curl_telnet(struct connectdata *conn) char *buf = data->state.buffer; ssize_t nread; struct TELNET *tn; + struct timeval now; /* current time */ code = init_telnet(conn); if(code) @@ -1148,9 +1150,13 @@ CURLcode Curl_telnet(struct connectdata *conn) keepfd = readfd; while (keepon) { + struct timeval interval; + readfd = keepfd; /* set this every lap in the loop */ + interval.tv_sec = 1; + interval.tv_usec = 0; - switch (select (sockfd + 1, &readfd, NULL, NULL, NULL)) { + switch (select (sockfd + 1, &readfd, NULL, NULL, &interval)) { case -1: /* error, stop reading */ keepon = FALSE; continue; @@ -1198,10 +1204,20 @@ CURLcode Curl_telnet(struct connectdata *conn) } } } + if(data->set.timeout) { + now = Curl_tvnow(); + if(Curl_tvdiff(now, conn->created)/1000 >= data->set.timeout) { + failf(data, "Time-out"); + code = CURLE_OPERATION_TIMEOUTED; + keepon = FALSE; + } + } } #endif /* mark this as "no further transfer wanted" */ - return Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + return code; } /* @@ -1211,3 +1227,4 @@ CURLcode Curl_telnet(struct connectdata *conn) * vim600: fdm=marker * vim: et sw=2 ts=2 sts=2 tw=78 */ +#endif diff --git a/Source/CTest/Curl/telnet.h b/Source/CTest/Curl/telnet.h index e576d1d..a985517 100644 --- a/Source/CTest/Curl/telnet.h +++ b/Source/CTest/Curl/telnet.h @@ -1,29 +1,30 @@ #ifndef __TELNET_H #define __TELNET_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET CURLcode Curl_telnet(struct connectdata *conn); CURLcode Curl_telnet_done(struct connectdata *conn); - +#endif #endif diff --git a/Source/CTest/Curl/timeval.c b/Source/CTest/Curl/timeval.c index cd44613..7ed6051 100644 --- a/Source/CTest/Curl/timeval.c +++ b/Source/CTest/Curl/timeval.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #ifdef WIN32 #include <windows.h> @@ -32,22 +32,40 @@ int gettimeofday (struct timeval *tp, void *nothing) { - SYSTEMTIME st; - time_t tt; - struct tm tmtm; - /* mktime converts local to UTC */ - GetLocalTime (&st); - tmtm.tm_sec = st.wSecond; - tmtm.tm_min = st.wMinute; - tmtm.tm_hour = st.wHour; - tmtm.tm_mday = st.wDay; - tmtm.tm_mon = st.wMonth - 1; - tmtm.tm_year = st.wYear - 1900; - tmtm.tm_isdst = -1; - tt = mktime (&tmtm); - tp->tv_sec = tt; - tp->tv_usec = st.wMilliseconds * 1000; - return 1; +#ifdef WITHOUT_MM_LIB + SYSTEMTIME st; + time_t tt; + struct tm tmtm; + /* mktime converts local to UTC */ + GetLocalTime (&st); + tmtm.tm_sec = st.wSecond; + tmtm.tm_min = st.wMinute; + tmtm.tm_hour = st.wHour; + tmtm.tm_mday = st.wDay; + tmtm.tm_mon = st.wMonth - 1; + tmtm.tm_year = st.wYear - 1900; + tmtm.tm_isdst = -1; + tt = mktime (&tmtm); + tp->tv_sec = tt; + tp->tv_usec = st.wMilliseconds * 1000; +#else + /** + ** The earlier time calculations using GetLocalTime + ** had a time resolution of 10ms.The timeGetTime, part + ** of multimedia apis offer a better time resolution + ** of 1ms.Need to link against winmm.lib for this + **/ + unsigned long Ticks = 0; + unsigned long Sec =0; + unsigned long Usec = 0; + Ticks = timeGetTime(); + + Sec = Ticks/1000; + Usec = (Ticks - (Sec*1000))*1000; + tp->tv_sec = Sec; + tp->tv_usec = Usec; +#endif + return 1; } #define HAVE_GETTIMEOFDAY #endif diff --git a/Source/CTest/Curl/timeval.h b/Source/CTest/Curl/timeval.h index c8ce593..b5ef901 100644 --- a/Source/CTest/Curl/timeval.h +++ b/Source/CTest/Curl/timeval.h @@ -1,27 +1,27 @@ #ifndef __TIMEVAL_H #define __TIMEVAL_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" diff --git a/Source/CTest/Curl/transfer.c b/Source/CTest/Curl/transfer.c index e4c1599..5e4e4fb 100644 --- a/Source/CTest/Curl/transfer.c +++ b/Source/CTest/Curl/transfer.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -82,6 +82,8 @@ #include <curl/types.h> #include "netrc.h" +#include "content_encoding.h" /* content encoding support. 08/27/02 jhrg */ + #include "hostip.h" #include "transfer.h" #include "sendf.h" @@ -168,6 +170,10 @@ compareheader(char *headerline, /* line to check */ return FALSE; /* no match */ } +/* We keep this static and global since this is read-only and NEVER + changed. It should just remain a blanked-out timeout value. */ +static struct timeval notimeout={0,0}; + CURLcode Curl_readwrite(struct connectdata *conn, bool *done) { @@ -176,14 +182,49 @@ CURLcode Curl_readwrite(struct connectdata *conn, int result; ssize_t nread; /* number of bytes read */ int didwhat=0; + + /* These two are used only if no other select() or _fdset() have been + invoked before this. This typicly happens if you use the multi interface + and call curl_multi_perform() without calling curl_multi_fdset() + first. */ + fd_set extrareadfd; + fd_set extrawritefd; + + fd_set *readfdp = k->readfdp; + fd_set *writefdp = k->writefdp; + + if((k->keepon & KEEP_READ) && !readfdp) { + /* reading is requested, but no socket descriptor pointer was set */ + FD_ZERO(&extrareadfd); + FD_SET(conn->sockfd, &extrareadfd); + readfdp = &extrareadfd; + + /* no write, no exceptions, no timeout */ + select(conn->sockfd+1, readfdp, NULL, NULL, ¬imeout); + } + if((k->keepon & KEEP_WRITE) && !writefdp) { + /* writing is requested, but no socket descriptor pointer was set */ + FD_ZERO(&extrawritefd); + FD_SET(conn->writesockfd, &extrawritefd); + writefdp = &extrawritefd; + + /* no read, no exceptions, no timeout */ + select(conn->writesockfd+1, NULL, writefdp, NULL, ¬imeout); + } do { + /* If we still have reading to do, we check if we have a readable + socket. Sometimes the reafdp is NULL, it no fd_set was done using + the multi interface and then we can do nothing but to attempt a + read to be sure. */ if((k->keepon & KEEP_READ) && - FD_ISSET(conn->sockfd, &k->readfd)) { + (FD_ISSET(conn->sockfd, readfdp))) { /* read! */ result = Curl_read(conn, conn->sockfd, k->buf, - BUFSIZE -1, &nread); + data->set.buffer_size? + data->set.buffer_size:BUFSIZE -1, + &nread); if(0>result) break; /* get out of loop */ @@ -215,6 +256,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, headers at the moment or not. */ if (k->header) { /* we are in parse-the-header-mode */ + bool stop_reading = FALSE; /* header line within buffer loop */ do { @@ -226,35 +268,43 @@ CURLcode Curl_readwrite(struct connectdata *conn, k->end_ptr = strchr (k->str_start, '\n'); if (!k->end_ptr) { - /* no more complete header lines within buffer */ - /* copy what is remaining into headerbuff */ - int str_length = (int)strlen(k->str); + /* Not a complete header line within buffer, append the data to + the end of the headerbuff. */ - /* - * We enlarge the header buffer if it seems to be too - * smallish - */ - if (k->hbuflen + (int)str_length >= - data->state.headersize) { + if (k->hbuflen + nread >= data->state.headersize) { + /* We enlarge the header buffer as it is too small */ char *newbuff; - long newsize=MAX((k->hbuflen+str_length)*3/2, + long newsize=MAX((k->hbuflen+nread)*3/2, data->state.headersize*2); hbufp_index = k->hbufp - data->state.headerbuff; newbuff = (char *)realloc(data->state.headerbuff, newsize); if(!newbuff) { failf (data, "Failed to alloc memory for big header!"); - return CURLE_READ_ERROR; + return CURLE_OUT_OF_MEMORY; } data->state.headersize=newsize; data->state.headerbuff = newbuff; k->hbufp = data->state.headerbuff + hbufp_index; } - strcpy (k->hbufp, k->str); - k->hbufp += strlen (k->str); - k->hbuflen += strlen (k->str); + memcpy(k->hbufp, k->str, nread); + k->hbufp += nread; + k->hbuflen += nread; + if (!k->headerline && (k->hbuflen>5)) { + /* make a first check that this looks like a HTTP header */ + if(!checkprefix("HTTP/", data->state.headerbuff)) { + /* this is not the beginning of a HTTP first header line */ + k->header = FALSE; + k->badheader = HEADER_ALLBAD; + break; + } + } + break; /* read more and try again */ } + /* decrease the size of the remaining buffer */ + nread -= (k->end_ptr - k->str)+1; + k->str = k->end_ptr + 1; /* move past new line */ /* @@ -273,7 +323,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, newbuff = (char *)realloc(data->state.headerbuff, newsize); if(!newbuff) { failf (data, "Failed to alloc memory for big header!"); - return CURLE_READ_ERROR; + return CURLE_OUT_OF_MEMORY; } data->state.headersize= newsize; data->state.headerbuff = newbuff; @@ -292,7 +342,19 @@ CURLcode Curl_readwrite(struct connectdata *conn, * We now have a FULL header line that p points to *****/ + if(!k->headerline) { + /* the first read header */ + if((k->hbuflen>5) && + !checkprefix("HTTP/", data->state.headerbuff)) { + /* this is not the beginning of a HTTP first header line */ + k->header = FALSE; + k->badheader = HEADER_PARTHEADER; + break; + } + } + if (('\n' == *k->p) || ('\r' == *k->p)) { + int headerlen; /* Zero-length header line means end of headers! */ if ('\r' == *k->p) @@ -327,7 +389,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, * we got: "417 Expectation Failed" this means: * we have made a HTTP call and our Expect Header * seems to cause a problem => abort the write operations - * (or prevent them from starting + * (or prevent them from starting). */ k->write_after_100_header = FALSE; k->keepon &= ~KEEP_WRITE; @@ -340,14 +402,16 @@ CURLcode Curl_readwrite(struct connectdata *conn, if (data->set.http_include_header) k->writetype |= CLIENTWRITE_BODY; + headerlen = k->p - data->state.headerbuff; + result = Curl_client_write(data, k->writetype, data->state.headerbuff, - k->p - data->state.headerbuff); + headerlen); if(result) return result; - data->info.header_size += k->p - data->state.headerbuff; - conn->headerbytecount += k->p - data->state.headerbuff; + data->info.header_size += headerlen; + conn->headerbytecount += headerlen; if(!k->header) { /* @@ -356,8 +420,6 @@ CURLcode Curl_readwrite(struct connectdata *conn, * If we requested a "no body", this is a good time to get * out and return home. */ - bool stop_reading = FALSE; - if(data->set.no_body) stop_reading = TRUE; else if(!conn->bits.close) { @@ -367,22 +429,16 @@ CURLcode Curl_readwrite(struct connectdata *conn, reading! */ if(-1 != conn->size) conn->maxdownload = conn->size; - - /* If max download size is *zero* (nothing) we already - have nothing and can safely return ok now! */ - if(0 == conn->maxdownload) - stop_reading = TRUE; - - /* What to do if the size is *not* known? */ } - + /* If max download size is *zero* (nothing) we already + have nothing and can safely return ok now! */ + if(0 == conn->maxdownload) + stop_reading = TRUE; + if(stop_reading) { /* we make sure that this socket isn't read more now */ k->keepon &= ~KEEP_READ; FD_ZERO(&k->rkeepfd); - /* for a progress meter/info update before going away */ - Curl_pgrsUpdate(conn); - return CURLE_OK; } break; /* exit header line loop */ @@ -451,6 +507,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, * NOT contain a message-body, and thus is always terminated * by the first empty line after the header fields. */ conn->size=0; + conn->maxdownload=0; break; default: /* nothing */ @@ -458,22 +515,23 @@ CURLcode Curl_readwrite(struct connectdata *conn, } } else { - k->header = FALSE; /* this is not a header line */ + k->header = FALSE; /* this is not a header line */ break; } } + /* check for Content-Length: header lines to get size */ - if (strnequal("Content-Length:", k->p, 15) && + if (checkprefix("Content-Length:", k->p) && sscanf (k->p+15, " %ld", &k->contentlength)) { conn->size = k->contentlength; Curl_pgrsSetDownloadSize(data, k->contentlength); - } + } /* check for Content-Type: header lines to get the mime-type */ - else if (strnequal("Content-Type:", k->p, 13)) { + else if (checkprefix("Content-Type:", k->p)) { char *start; char *end; int len; - + /* Find the first non-space letter */ for(start=k->p+14; *start && isspace((int)*start); @@ -539,7 +597,35 @@ CURLcode Curl_readwrite(struct connectdata *conn, /* init our chunky engine */ Curl_httpchunk_init(conn); } - else if (strnequal("Content-Range:", k->p, 14)) { + else if (checkprefix("Content-Encoding:", k->p) && + data->set.encoding) { + /* + * Process Content-Encoding. Look for the values: identity, gzip, + * defalte, compress, x-gzip and x-compress. x-gzip and + * x-compress are the same as gzip and compress. (Sec 3.5 RFC + * 2616). zlib cannot handle compress, and gzip is not currently + * implemented. However, errors are handled further down when the + * response body is processed 08/27/02 jhrg */ + char *start; + + /* Find the first non-space letter */ + for(start=k->p+17; + *start && isspace((int)*start); + start++); + + /* Record the content-encoding for later use. 08/27/02 jhrg */ + if (checkprefix("identity", start)) + k->content_encoding = IDENTITY; + else if (checkprefix("deflate", start)) + k->content_encoding = DEFLATE; + else if (checkprefix("gzip", start) + || checkprefix("x-gzip", start)) + k->content_encoding = GZIP; + else if (checkprefix("compress", start) + || checkprefix("x-compress", start)) + k->content_encoding = COMPRESS; + } + else if (checkprefix("Content-Range:", k->p)) { if (sscanf (k->p+14, " bytes %d-", &k->offset) || sscanf (k->p+14, " bytes: %d-", &k->offset)) { /* This second format was added August 1st 2000 by Igor @@ -552,11 +638,10 @@ CURLcode Curl_readwrite(struct connectdata *conn, } } else if(data->cookies && - strnequal("Set-Cookie:", k->p, 11)) { - Curl_cookie_add(data->cookies, TRUE, k->p+12, conn->name); + checkprefix("Set-Cookie:", k->p)) { + Curl_cookie_add(data->cookies, TRUE, k->p+11, conn->name); } - else if(strnequal("Last-Modified:", k->p, - strlen("Last-Modified:")) && + else if(checkprefix("Last-Modified:", k->p) && (data->set.timecondition || data->set.get_filetime) ) { time_t secs=time(NULL); k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"), @@ -566,7 +651,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, } else if ((k->httpcode >= 300 && k->httpcode < 400) && (data->set.http_follow_location) && - strnequal("Location:", k->p, 9)) { + checkprefix("Location:", k->p)) { /* this is the URL that the server advices us to get instead */ char *ptr; char *start=k->p; @@ -584,9 +669,11 @@ CURLcode Curl_readwrite(struct connectdata *conn, while(*ptr && !isspace((int)*ptr)) ptr++; backup = *ptr; /* store the ending letter */ - *ptr = '\0'; /* zero terminate */ - conn->newurl = strdup(start); /* clone string */ - *ptr = backup; /* restore ending letter */ + if(ptr != start) { + *ptr = '\0'; /* zero terminate */ + conn->newurl = strdup(start); /* clone string */ + *ptr = backup; /* restore ending letter */ + } } /* @@ -597,6 +684,10 @@ CURLcode Curl_readwrite(struct connectdata *conn, if (data->set.http_include_header) k->writetype |= CLIENTWRITE_BODY; + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + k->p, k->hbuflen); + result = Curl_client_write(data, k->writetype, k->p, k->hbuflen); if(result) @@ -609,20 +700,16 @@ CURLcode Curl_readwrite(struct connectdata *conn, k->hbufp = data->state.headerbuff; k->hbuflen = 0; } - while (*k->str); /* header line within buffer */ + while (!stop_reading && *k->str); /* header line within buffer */ + + if(stop_reading) + /* We've stopped dealing with input, get out of the do-while loop */ + break; /* We might have reached the end of the header part here, but there might be a non-header part left in the end of the read buffer. */ - if (!k->header) { - /* the next token and forward is not part of - the header! */ - - /* we subtract the remaining header size from the buffer */ - nread -= (k->str - k->buf); - } - } /* end if header mode */ /* This is not an 'else if' since it may be a rest from the header @@ -638,8 +725,9 @@ CURLcode Curl_readwrite(struct connectdata *conn, if (conn->newurl) { /* abort after the headers if "follow Location" is set */ infof (data, "Follow to new URL: %s\n", conn->newurl); - k->keepon &= ~KEEP_READ; - FD_ZERO(&k->rkeepfd); + k->keepon &= ~KEEP_READ; + FD_ZERO(&k->rkeepfd); + *done = TRUE; return CURLE_OK; } else if (conn->resume_from && @@ -664,6 +752,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, if(k->timeofdoc < data->set.timevalue) { infof(data, "The requested document is not new enough\n"); + *done = TRUE; return CURLE_OK; } break; @@ -671,6 +760,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, if(k->timeofdoc > data->set.timevalue) { infof(data, "The requested document is not old enough\n"); + *done = TRUE; return CURLE_OK; } break; @@ -682,6 +772,18 @@ CURLcode Curl_readwrite(struct connectdata *conn, } /* this is the first time we write a body part */ k->bodywrites++; + /* pass data to the debug function before it gets "dechunked" */ + if(data->set.verbose) { + if(k->badheader) { + Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff, + k->hbuflen); + if(k->badheader == HEADER_PARTHEADER) + Curl_debug(data, CURLINFO_DATA_IN, k->str, nread); + } + else + Curl_debug(data, CURLINFO_DATA_IN, k->str, nread); + } + if(conn->bits.chunk) { /* * Bless me father for I have sinned. Here comes a chunked @@ -693,8 +795,12 @@ CURLcode Curl_readwrite(struct connectdata *conn, Curl_httpchunk_read(conn, k->str, nread, &nread); if(CHUNKE_OK < res) { - failf(data, "Receeived problem in the chunky parser"); - return CURLE_READ_ERROR; + if(CHUNKE_WRITE_ERROR == res) { + failf(data, "Failed writing data"); + return CURLE_WRITE_ERROR; + } + failf(data, "Received problem in the chunky parser"); + return CURLE_RECV_ERROR; } else if(CHUNKE_STOP == res) { /* we're done reading chunks! */ @@ -722,10 +828,51 @@ CURLcode Curl_readwrite(struct connectdata *conn, Curl_pgrsSetDownloadCounter(data, (double)k->bytecount); - if(!conn->bits.chunk && nread) { + if(!conn->bits.chunk && (nread || k->badheader)) { /* If this is chunky transfer, it was already written */ - result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, - nread); + + if(k->badheader) { + /* we parsed a piece of data wrongly assuming it was a header + and now we output it as body instead */ + result = Curl_client_write(data, CLIENTWRITE_BODY, + data->state.headerbuff, + k->hbuflen); + } + if(k->badheader < HEADER_ALLBAD) { + /* This switch handles various content encodings. If there's an + error here, be sure to check over the almost identical code in + http_chunk.c. 08/29/02 jhrg */ +#ifdef HAVE_LIBZ + switch (k->content_encoding) { + case IDENTITY: +#endif + /* This is the default when the server sends no + Content-Encoding header. See Curl_readwrite_init; the + memset() call initializes k->content_encoding to zero. + 08/28/02 jhrg */ + result = Curl_client_write(data, CLIENTWRITE_BODY, k->str, + nread); +#ifdef HAVE_LIBZ + break; + + case DEFLATE: + /* Assume CLIENTWRITE_BODY; headers are not encoded. */ + result = Curl_unencode_deflate_write(data, k, nread); + break; + + case GZIP: /* FIXME 08/27/02 jhrg */ + case COMPRESS: + default: + failf (data, "Unrecognized content encoding type. " + "libcurl understands `identity' and `deflate' " + "content encodings."); + result = CURLE_BAD_CONTENT_ENCODING; + break; + } +#endif + } + k->badheader = HEADER_NORMAL; /* taken care of now */ + if(result) return result; } @@ -733,8 +880,12 @@ CURLcode Curl_readwrite(struct connectdata *conn, } /* if (! header and data to read ) */ } /* if( read from socket ) */ + /* If we still have writing to do, we check if we have a writable + socket. Sometimes the writefdp is NULL, it no fd_set was done using + the multi interface and then we can do nothing but to attempt a + write to be sure. */ if((k->keepon & KEEP_WRITE) && - FD_ISSET(conn->writesockfd, &k->writefd)) { + (FD_ISSET(conn->writesockfd, writefdp)) ) { /* write */ int i, si; @@ -748,11 +899,46 @@ CURLcode Curl_readwrite(struct connectdata *conn, /* only read more data if there's no upload data already present in the upload buffer */ if(0 == conn->upload_present) { + size_t buffersize = BUFSIZE; /* init the "upload from here" pointer */ conn->upload_fromhere = k->uploadbuf; - nread = data->set.fread(conn->upload_fromhere, 1, - BUFSIZE, data->set.in); + if(!k->upload_done) { + + if(conn->bits.upload_chunky) { + /* if chunked Transfer-Encoding */ + buffersize -= (8 + 2 + 2); /* 32bit hex + CRLF + CRLF */ + conn->upload_fromhere += 10; /* 32bit hex + CRLF */ + } + + nread = data->set.fread(conn->upload_fromhere, 1, + buffersize, data->set.in); + + if(conn->bits.upload_chunky) { + /* if chunked Transfer-Encoding */ + char hexbuffer[9]; + int hexlen = snprintf(hexbuffer, sizeof(hexbuffer), + "%x\r\n", nread); + /* move buffer pointer */ + conn->upload_fromhere -= hexlen; + nread += hexlen; + + /* copy the prefix to the buffer */ + memcpy(conn->upload_fromhere, hexbuffer, hexlen); + if(nread>0) { + /* append CRLF to the data */ + memcpy(conn->upload_fromhere + + nread, "\r\n", 2); + nread+=2; + } + else { + /* mark this as done once this chunk is transfered */ + k->upload_done = TRUE; + } + } + } + else + nread = 0; /* we're done uploading/reading */ /* the signed int typecase of nread of for systems that has unsigned size_t */ @@ -769,16 +955,24 @@ CURLcode Curl_readwrite(struct connectdata *conn, /* convert LF to CRLF if so asked */ if (data->set.crlf) { for(i = 0, si = 0; i < nread; i++, si++) { - if (k->buf[i] == 0x0a) { + if (conn->upload_fromhere[i] == 0x0a) { data->state.scratch[si++] = 0x0d; data->state.scratch[si] = 0x0a; } - else { - data->state.scratch[si] = k->uploadbuf[i]; - } + else + data->state.scratch[si] = conn->upload_fromhere[i]; + } + if(si != nread) { + /* only perform the special operation if we really did replace + anything */ + nread = si; + + /* upload from the new (replaced) buffer instead */ + conn->upload_fromhere = data->state.scratch; + + /* set the new amount too */ + conn->upload_present = nread; } - nread = si; - k->buf = data->state.scratch; /* point to the new buffer */ } } else { @@ -804,14 +998,23 @@ CURLcode Curl_readwrite(struct connectdata *conn, is to happen */ conn->upload_fromhere += bytes_written; } - else if(data->set.crlf) - k->buf = data->state.buffer; /* put it back on the buffer */ else { /* we've uploaded that buffer now */ conn->upload_fromhere = k->uploadbuf; conn->upload_present = 0; /* no more bytes left */ + + if(k->upload_done) { + /* switch off writing, we're done! */ + k->keepon &= ~KEEP_WRITE; /* we're done writing */ + FD_ZERO(&k->wkeepfd); + } } + if(data->set.verbose) + Curl_debug(data, CURLINFO_DATA_OUT, conn->upload_fromhere, + bytes_written); + + k->writebytecount += bytes_written; Curl_pgrsSetUploadCounter(data, (double)k->writebytecount); @@ -887,13 +1090,14 @@ CURLcode Curl_readwrite_init(struct connectdata *conn) struct SessionHandle *data = conn->data; struct Curl_transfer_keeper *k = &conn->keep; + /* NB: the content encoding software depends on this initialization of + Curl_transfer_keeper. 08/28/02 jhrg */ memset(k, 0, sizeof(struct Curl_transfer_keeper)); k->start = Curl_tvnow(); /* start time */ k->now = k->start; /* current time is now */ k->header = TRUE; /* assume header */ k->httpversion = -1; /* unknown at this point */ - k->conn = (struct connectdata *)conn; /* store the connection */ data = conn->data; /* there's the root struct */ k->buf = data->state.buffer; @@ -905,13 +1109,16 @@ CURLcode Curl_readwrite_init(struct connectdata *conn) Curl_pgrsTime(data, TIMER_PRETRANSFER); Curl_speedinit(data); - if (!conn->getheader) { + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + + if (!conn->bits.getheader) { k->header = FALSE; if(conn->size > 0) Curl_pgrsSetDownloadSize(data, conn->size); } /* we want header and/or body, if neither then don't do this! */ - if(conn->getheader || !data->set.no_body) { + if(conn->bits.getheader || !data->set.no_body) { FD_ZERO (&k->readfd); /* clear it */ if(conn->sockfd != -1) { @@ -950,11 +1157,13 @@ void Curl_single_fdset(struct connectdata *conn, if(conn->keep.keepon & KEEP_READ) { FD_SET(conn->sockfd, read_fd_set); *max_fd = conn->sockfd; + conn->keep.readfdp = read_fd_set; /* store the address of the set */ } if(conn->keep.keepon & KEEP_WRITE) { FD_SET(conn->writesockfd, write_fd_set); if(conn->writesockfd > *max_fd) *max_fd = conn->writesockfd; + conn->keep.writefdp = write_fd_set; /* store the address of the set */ } /* we don't use exceptions, only touch that one to prevent compiler warnings! */ @@ -991,9 +1200,12 @@ Transfer(struct connectdata *conn) return CURLE_OK; /* we want header and/or body, if neither then don't do this! */ - if(!conn->getheader && data->set.no_body) + if(!conn->bits.getheader && data->set.no_body) return CURLE_OK; + k->writefdp = &k->writefd; /* store the address of the set */ + k->readfdp = &k->readfd; /* store the address of the set */ + while (!done) { struct timeval interval; k->readfd = k->rkeepfd; /* set these every lap in the loop */ @@ -1001,8 +1213,7 @@ Transfer(struct connectdata *conn) interval.tv_sec = 1; interval.tv_usec = 0; - switch (select (k->maxfd, &k->readfd, &k->writefd, NULL, - &interval)) { + switch (select (k->maxfd, k->readfdp, k->writefdp, NULL, &interval)) { case -1: /* select() error, stop reading */ #ifdef EINTR /* The EINTR is not serious, and it seems you might get this more @@ -1047,6 +1258,22 @@ CURLcode Curl_pretransfer(struct SessionHandle *data) data->state.this_is_a_follow = FALSE; /* reset this */ data->state.errorbuf = FALSE; /* no error has occurred */ + /* If there was a list of cookie files to read and we haven't done it before, + do it now! */ + if(data->change.cookielist) { + struct curl_slist *list = data->change.cookielist; + while(list) { + data->cookies = Curl_cookie_init(list->data, + data->cookies, + data->set.cookiesession); + list = list->next; + } + curl_slist_free_all(data->change.cookielist); /* clean up list */ + data->change.cookielist = NULL; /* don't do this again! */ + } + + + /* Allow data->set.use_port to set which port to use. This needs to be * disabled for example when we follow Location: headers to URLs using * different ports! */ @@ -1056,7 +1283,8 @@ CURLcode Curl_pretransfer(struct SessionHandle *data) /************************************************************* * Tell signal handler to ignore SIGPIPE *************************************************************/ - data->state.prev_signal = signal(SIGPIPE, SIG_IGN); + if(!data->set.no_signal) + data->state.prev_signal = signal(SIGPIPE, SIG_IGN); #endif Curl_initinfo(data); /* reset session-specific information "variables" */ @@ -1069,12 +1297,245 @@ CURLcode Curl_posttransfer(struct SessionHandle *data) { #if defined(HAVE_SIGNAL) && defined(SIGPIPE) /* restore the signal handler for SIGPIPE before we get back */ - signal(SIGPIPE, data->state.prev_signal); + if(!data->set.no_signal) + signal(SIGPIPE, data->state.prev_signal); #endif return CURLE_OK; } +CURLcode Curl_follow(struct SessionHandle *data, + char *newurl) /* this 'newurl' is the Location: string, + and it must be malloc()ed before passed + here */ +{ + /* Location: redirect */ + char prot[16]; /* URL protocol string storage */ + char letter; /* used for a silly sscanf */ + + if (data->set.maxredirs && + (data->set.followlocation >= data->set.maxredirs)) { + failf(data,"Maximum (%d) redirects followed", data->set.maxredirs); + return CURLE_TOO_MANY_REDIRECTS; + } + + /* mark the next request as a followed location: */ + data->state.this_is_a_follow = TRUE; + + data->set.followlocation++; /* count location-followers */ + + if(data->set.http_auto_referer) { + /* We are asked to automatically set the previous URL as the + referer when we get the next URL. We pick the ->url field, + which may or may not be 100% correct */ + + if(data->change.referer_alloc) + /* If we already have an allocated referer, free this first */ + free(data->change.referer); + + data->change.referer = strdup(data->change.url); + data->change.referer_alloc = TRUE; /* yes, free this later */ + } + + if(2 != sscanf(newurl, "%15[^?&/:]://%c", prot, &letter)) { + /*** + *DANG* this is an RFC 2068 violation. The URL is supposed + to be absolute and this doesn't seem to be that! + *** + Instead, we have to TRY to append this new path to the old URL + to the right of the host part. Oh crap, this is doomed to cause + problems in the future... + */ + char *protsep; + char *pathsep; + char *newest; + + char *useurl = newurl; + + /* we must make our own copy of the URL to play with, as it may + point to read-only data */ + char *url_clone=strdup(data->change.url); + + if(!url_clone) + return CURLE_OUT_OF_MEMORY; /* skip out of this NOW */ + + /* protsep points to the start of the host name */ + protsep=strstr(url_clone, "//"); + if(!protsep) + protsep=url_clone; + else + protsep+=2; /* pass the slashes */ + + if('/' != newurl[0]) { + int level=0; + + /* First we need to find out if there's a ?-letter in the URL, + and cut it and the right-side of that off */ + pathsep = strrchr(protsep, '?'); + if(pathsep) + *pathsep=0; + + /* we have a relative path to append to the last slash if + there's one available */ + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep=0; + + /* Check if there's any slash after the host name, and if so, + remember that position instead */ + pathsep = strchr(protsep, '/'); + if(pathsep) + protsep = pathsep+1; + else + protsep = NULL; + + /* now deal with one "./" or any amount of "../" in the newurl + and act accordingly */ + + if((useurl[0] == '.') && (useurl[1] == '/')) + useurl+=2; /* just skip the "./" */ + + while((useurl[0] == '.') && + (useurl[1] == '.') && + (useurl[2] == '/')) { + level++; + useurl+=3; /* pass the "../" */ + } + + if(protsep) { + while(level--) { + /* cut off one more level from the right of the original URL */ + pathsep = strrchr(protsep, '/'); + if(pathsep) + *pathsep=0; + else { + *protsep=0; + break; + } + } + } + } + else { + /* We got a new absolute path for this server, cut off from the + first slash */ + pathsep = strchr(protsep, '/'); + if(pathsep) + *pathsep=0; + } + + newest=(char *)malloc( strlen(url_clone) + + 1 + /* possible slash */ + strlen(useurl) + 1/* zero byte */); + + if(!newest) + return CURLE_OUT_OF_MEMORY; /* go out from this */ + + sprintf(newest, "%s%s%s", url_clone, + (('/' == useurl[0]) || (protsep && !*protsep))?"":"/", + useurl); + free(newurl); /* newurl is the allocated pointer */ + free(url_clone); + newurl = newest; + } + else + /* This is an absolute URL, don't allow the custom port number */ + data->state.allow_port = FALSE; + + if(data->change.url_alloc) + free(data->change.url); + else + data->change.url_alloc = TRUE; /* the URL is allocated */ + + /* TBD: set the URL with curl_setopt() */ + data->change.url = newurl; + newurl = NULL; /* don't free! */ + + infof(data, "Follows Location: to new URL: '%s'\n", data->change.url); + + /* + * We get here when the HTTP code is 300-399. We need to perform + * differently based on exactly what return code there was. + * Discussed on the curl mailing list and posted about on the 26th + * of January 2001. + */ + switch(data->info.httpcode) { + case 300: /* Multiple Choices */ + case 306: /* Not used */ + case 307: /* Temporary Redirect */ + default: /* for all unknown ones */ + /* These are explicitly mention since I've checked RFC2616 and they + * seem to be OK to POST to. + */ + break; + case 301: /* Moved Permanently */ + /* (quote from RFC2616, section 10.3.2): + * + * Note: When automatically redirecting a POST request after + * receiving a 301 status code, some existing HTTP/1.0 user agents + * will erroneously change it into a GET request. + * + * ---- + * Warning: Because most of importants user agents do this clear + * RFC2616 violation, many webservers expect this misbehavior. So + * these servers often answers to a POST request with an error page. + * To be sure that libcurl gets the page that most user agents + * would get, libcurl has to force GET: + */ + if( data->set.httpreq == HTTPREQ_POST + || data->set.httpreq == HTTPREQ_POST_FORM) { + infof(data, + "Violate RFC 2616/10.3.2 and switch from POST to GET\n"); + data->set.httpreq = HTTPREQ_GET; + } + break; + case 302: /* Found */ + /* (From 10.3.3) + + Note: RFC 1945 and RFC 2068 specify that the client is not allowed + to change the method on the redirected request. However, most + existing user agent implementations treat 302 as if it were a 303 + response, performing a GET on the Location field-value regardless + of the original request method. The status codes 303 and 307 have + been added for servers that wish to make unambiguously clear which + kind of reaction is expected of the client. + + (From 10.3.4) + + Note: Many pre-HTTP/1.1 user agents do not understand the 303 + status. When interoperability with such clients is a concern, the + 302 status code may be used instead, since most user agents react + to a 302 response as described here for 303. + */ + case 303: /* See Other */ + /* Disable both types of POSTs, since doing a second POST when + * following isn't what anyone would want! */ + if(data->set.httpreq != HTTPREQ_GET) { + data->set.httpreq = HTTPREQ_GET; /* enforce GET request */ + infof(data, "Disables POST, goes with %s\n", + data->set.no_body?"HEAD":"GET"); + } + break; + case 304: /* Not Modified */ + /* 304 means we did a conditional request and it was "Not modified". + * We shouldn't get any Location: header in this response! + */ + break; + case 305: /* Use Proxy */ + /* (quote from RFC2616, section 10.3.6): + * "The requested resource MUST be accessed through the proxy given + * by the Location field. The Location field gives the URI of the + * proxy. The recipient is expected to repeat this single request + * via the proxy. 305 responses MUST only be generated by origin + * servers." + */ + break; + } + Curl_pgrsTime(data, TIMER_REDIRECT); + Curl_pgrsResetTimes(data); + + return CURLE_OK; +} + CURLcode Curl_perform(struct SessionHandle *data) { CURLcode res; @@ -1082,15 +1543,17 @@ CURLcode Curl_perform(struct SessionHandle *data) struct connectdata *conn=NULL; char *newurl = NULL; /* possibly a new URL to follow to! */ + data->state.used_interface = Curl_if_easy; + res = Curl_pretransfer(data); if(res) return res; /* - * It is important that there is NO 'return' from this function any any - * other place than falling down the bottom! This is because we have cleanup - * stuff that must be done before we get back, and that is only performed - * after this do-while loop. + * It is important that there is NO 'return' from this function at any other + * place than falling down to the end of the function! This is because we + * have cleanup stuff that must be done before we get back, and that is only + * performed after this do-while loop. */ do { @@ -1116,12 +1579,20 @@ CURLcode Curl_perform(struct SessionHandle *data) * may be free()ed in the Curl_done() function. */ newurl = conn->newurl?strdup(conn->newurl):NULL; - else + else { /* The transfer phase returned error, we mark the connection to get * closed to prevent being re-used. This is becasue we can't * possibly know if the connection is in a good shape or not now. */ conn->bits.close = TRUE; + if(-1 !=conn->secondarysocket) { + /* if we failed anywhere, we must clean up the secondary socket if + it was used */ + sclose(conn->secondarysocket); + conn->secondarysocket=-1; + } + } + /* Always run Curl_done(), even if some of the previous calls failed, but return the previous (original) error code */ res2 = Curl_done(conn); @@ -1136,172 +1607,11 @@ CURLcode Curl_perform(struct SessionHandle *data) */ if((res == CURLE_OK) && newurl) { - /* Location: redirect - - This is assumed to happen for HTTP(S) only! - */ - char prot[16]; /* URL protocol string storage */ - char letter; /* used for a silly sscanf */ - - if (data->set.maxredirs && (data->set.followlocation >= data->set.maxredirs)) { - failf(data,"Maximum (%d) redirects followed", data->set.maxredirs); - res=CURLE_TOO_MANY_REDIRECTS; - break; - } - - /* mark the next request as a followed location: */ - data->state.this_is_a_follow = TRUE; - - data->set.followlocation++; /* count location-followers */ - - if(data->set.http_auto_referer) { - /* We are asked to automatically set the previous URL as the - referer when we get the next URL. We pick the ->url field, - which may or may not be 100% correct */ - - if(data->change.referer_alloc) - /* If we already have an allocated referer, free this first */ - free(data->change.referer); - - data->change.referer = strdup(data->change.url); - data->change.referer_alloc = TRUE; /* yes, free this later */ - } - - if(2 != sscanf(newurl, "%15[^?&/:]://%c", prot, &letter)) { - /*** - *DANG* this is an RFC 2068 violation. The URL is supposed - to be absolute and this doesn't seem to be that! - *** - Instead, we have to TRY to append this new path to the old URL - to the right of the host part. Oh crap, this is doomed to cause - problems in the future... - */ - char *protsep; - char *pathsep; - char *newest; - - /* we must make our own copy of the URL to play with, as it may - point to read-only data */ - char *url_clone=strdup(data->change.url); - - if(!url_clone) { - res = CURLE_OUT_OF_MEMORY; - break; /* skip out of this loop NOW */ - } - - /* protsep points to the start of the host name */ - protsep=strstr(url_clone, "//"); - if(!protsep) - protsep=url_clone; - else - protsep+=2; /* pass the slashes */ - - if('/' != newurl[0]) { - /* First we need to find out if there's a ?-letter in the URL, - and cut it and the right-side of that off */ - pathsep = strrchr(protsep, '?'); - if(pathsep) - *pathsep=0; - - /* we have a relative path to append to the last slash if - there's one available */ - pathsep = strrchr(protsep, '/'); - if(pathsep) - *pathsep=0; - } - else { - /* We got a new absolute path for this server, cut off from the - first slash */ - pathsep = strchr(protsep, '/'); - if(pathsep) - *pathsep=0; - } - - newest=(char *)malloc( strlen(url_clone) + - 1 + /* possible slash */ - strlen(newurl) + 1/* zero byte */); - - if(!newest) { - res = CURLE_OUT_OF_MEMORY; - break; /* go go go out from this loop */ - } - sprintf(newest, "%s%s%s", url_clone, ('/' == newurl[0])?"":"/", - newurl); - free(newurl); - free(url_clone); - newurl = newest; - } - else - /* This is an absolute URL, don't allow the custom port number */ - data->state.allow_port = FALSE; - - if(data->change.url_alloc) - free(data->change.url); - else - data->change.url_alloc = TRUE; /* the URL is allocated */ - - /* TBD: set the URL with curl_setopt() */ - data->change.url = newurl; - newurl = NULL; /* don't free! */ - - infof(data, "Follows Location: to new URL: '%s'\n", data->change.url); - - /* - * We get here when the HTTP code is 300-399. We need to perform - * differently based on exactly what return code there was. - * Discussed on the curl mailing list and posted about on the 26th - * of January 2001. - */ - switch(data->info.httpcode) { - case 300: /* Multiple Choices */ - case 301: /* Moved Permanently */ - case 306: /* Not used */ - case 307: /* Temporary Redirect */ - default: /* for all unknown ones */ - /* These are explicitly mention since I've checked RFC2616 and they - * seem to be OK to POST to. - */ - break; - case 302: /* Found */ - /* (From 10.3.3) - - Note: RFC 1945 and RFC 2068 specify that the client is not allowed - to change the method on the redirected request. However, most - existing user agent implementations treat 302 as if it were a 303 - response, performing a GET on the Location field-value regardless - of the original request method. The status codes 303 and 307 have - been added for servers that wish to make unambiguously clear which - kind of reaction is expected of the client. - - (From 10.3.4) - - Note: Many pre-HTTP/1.1 user agents do not understand the 303 - status. When interoperability with such clients is a concern, the - 302 status code may be used instead, since most user agents react - to a 302 response as described here for 303. - */ - case 303: /* See Other */ - /* Disable both types of POSTs, since doing a second POST when - * following isn't what anyone would want! */ - data->set.httpreq = HTTPREQ_GET; /* enforce GET request */ - infof(data, "Disables POST, goes with GET\n"); - break; - case 304: /* Not Modified */ - /* 304 means we did a conditional request and it was "Not modified". - * We shouldn't get any Location: header in this response! - */ - break; - case 305: /* Use Proxy */ - /* (quote from RFC2616, section 10.3.6): - * "The requested resource MUST be accessed through the proxy given - * by the Location field. The Location field gives the URI of the - * proxy. The recipient is expected to repeat this single request - * via the proxy. 305 responses MUST only be generated by origin - * servers." - */ - break; + res = Curl_follow(data, newurl); + if(CURLE_OK == res) { + newurl = NULL; + continue; } - continue; } } break; /* it only reaches here when this shouldn't loop */ @@ -1339,7 +1649,7 @@ Curl_Transfer(struct connectdata *c_conn, /* connection data */ /* now copy all input parameters */ conn->sockfd = sockfd; conn->size = size; - conn->getheader = getheader; + conn->bits.getheader = getheader; conn->bytecountp = bytecountp; conn->writesockfd = writesockfd; conn->writebytecountp = writebytecountp; diff --git a/Source/CTest/Curl/transfer.h b/Source/CTest/Curl/transfer.h index ee6c93d..cc15343 100644 --- a/Source/CTest/Curl/transfer.h +++ b/Source/CTest/Curl/transfer.h @@ -1,32 +1,31 @@ #ifndef __TRANSFER_H #define __TRANSFER_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ CURLcode Curl_perform(struct SessionHandle *data); - CURLcode Curl_pretransfer(struct SessionHandle *data); CURLcode Curl_posttransfer(struct SessionHandle *data); - +CURLcode Curl_follow(struct SessionHandle *data, char *newurl); CURLcode Curl_readwrite(struct connectdata *conn, bool *done); void Curl_single_fdset(struct connectdata *conn, fd_set *read_fd_set, diff --git a/Source/CTest/Curl/url.c b/Source/CTest/Curl/url.c index d830fb6..3216fd6 100644 --- a/Source/CTest/Curl/url.c +++ b/Source/CTest/Curl/url.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* -- WIN32 approved -- */ @@ -72,6 +72,10 @@ #include <inet.h> #endif +#ifdef HAVE_SETJMP_H +#include <setjmp.h> +#endif + #ifndef HAVE_SELECT #error "We can't compile without select() support!" #endif @@ -107,6 +111,7 @@ #include "ldap.h" #include "url.h" #include "connect.h" +#include "ca-bundle.h" #include <curl/types.h> @@ -120,6 +125,7 @@ #ifdef KRB4 #include "security.h" #endif + /* The last #include file should be: */ #ifdef MALLOCDEBUG #include "memdebug.h" @@ -138,11 +144,17 @@ static unsigned int ConnectionStore(struct SessionHandle *data, #ifndef RETSIGTYPE #define RETSIGTYPE void #endif +#ifdef HAVE_SIGSETJMP +extern sigjmp_buf curl_jmpenv; +#endif static RETSIGTYPE alarmfunc(int signal) { /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ (void)signal; +#ifdef HAVE_SIGSETJMP + siglongjmp(curl_jmpenv, 1); +#endif return; } #endif @@ -167,6 +179,13 @@ CURLcode Curl_close(struct SessionHandle *data) Curl_SSL_Close_All(data); #endif + /* No longer a dirty share, if it exists */ + if (data->share) + data->share->dirty--; + + if(data->change.cookielist) /* clean up list if any */ + curl_slist_free_all(data->change.cookielist); + if(data->state.auth_host) free(data->state.auth_host); @@ -182,11 +201,13 @@ CURLcode Curl_close(struct SessionHandle *data) if(data->state.headerbuff) free(data->state.headerbuff); +#ifndef CURL_DISABLE_HTTP if(data->set.cookiejar) /* we have a "destination" for all the cookies to get dumped to */ Curl_cookie_output(data->cookies, data->set.cookiejar); Curl_cookie_cleanup(data->cookies); +#endif /* free the connection cache */ free(data->state.connects); @@ -262,7 +283,11 @@ CURLcode Curl_open(struct SessionHandle **curl) /* Set the default size of the SSL session ID cache */ data->set.ssl.numsessions = 5; + + data->set.proxyport = 1080; + data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ + /* create an array with connection data struct pointers */ data->state.numconnects = 5; /* hard-coded right now */ data->state.connects = (struct connectdata **) @@ -272,12 +297,23 @@ CURLcode Curl_open(struct SessionHandle **curl) free(data); return CURLE_OUT_OF_MEMORY; } - + + /* + * libcurl 7.10 introduces SSL verification *by default*! This needs to be + * switched off unless wanted. + */ + data->set.ssl.verifypeer = TRUE; + data->set.ssl.verifyhost = 2; +#ifdef CURL_CA_BUNDLE + /* This is our prefered CA cert bundle since install time */ + data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE; +#endif + + memset(data->state.connects, 0, sizeof(struct connectdata *)*data->state.numconnects); *curl = data; - return CURLE_OK; } @@ -439,7 +475,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) /* * Parse the $HOME/.netrc file */ - data->set.use_netrc = va_arg(param, long)?TRUE:FALSE; + data->set.use_netrc = va_arg(param, long); break; case CURLOPT_FOLLOWLOCATION: /* @@ -493,13 +529,36 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) data->set.ssl.version = va_arg(param, long); break; + case CURLOPT_COOKIESESSION: + /* + * Set this option to TRUE to start a new "cookie session". It will + * prevent the forthcoming read-cookies-from-file actions to accept + * cookies that are marked as being session cookies, as they belong to a + * previous session. + * + * In the original Netscape cookie spec, "session cookies" are cookies + * with no expire date set. RFC2109 describes the same action if no + * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds + * a 'Discard' action that can enforce the discard even for cookies that + * have a Max-Age. + * + * We run mostly with the original cookie spec, as hardly anyone implements + * anything else. + */ + data->set.cookiesession = (bool)va_arg(param, long); + break; + +#ifndef CURL_DISABLE_HTTP case CURLOPT_COOKIEFILE: /* * Set cookie file to read and parse. Can be used multiple times. */ cookiefile = (char *)va_arg(param, void *); if(cookiefile) - data->cookies = Curl_cookie_init(cookiefile, data->cookies); + /* append the cookie file name to the list of file names, and deal with + them later */ + data->change.cookielist = + curl_slist_append(data->change.cookielist, cookiefile); break; case CURLOPT_COOKIEJAR: @@ -512,8 +571,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) * Activate the cookie parser. This may or may not already * have been made. */ - data->cookies = Curl_cookie_init(NULL, data->cookies); + data->cookies = Curl_cookie_init(NULL, data->cookies, + data->set.cookiesession); break; +#endif + case CURLOPT_WRITEHEADER: /* * Custom pointer to pass the header write callback function @@ -634,8 +696,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) data->set.use_port = va_arg(param, long); break; case CURLOPT_POST: - /* Does this option serve a purpose anymore? */ - + /* Does this option serve a purpose anymore? Yes it does, when + CURLOPT_POSTFIELDS isn't used and the POST data is read off the + callback! */ if(va_arg(param, long)) data->set.httpreq = HTTPREQ_POST; break; @@ -673,7 +736,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) break; case CURLOPT_PROXY: /* - * Set proxy server:port to use as HTTP proxy + * Set proxy server:port to use as HTTP proxy. + * + * If the proxy is set to "" we explicitly say that we don't want to use a + * proxy (even though there might be environment variables saying so). + * + * Setting it to NULL, means no proxy but allows the environment variables + * to decide for us. */ if(data->change.proxy_alloc) { /* @@ -723,6 +792,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) */ data->set.useragent = va_arg(param, char *); break; + case CURLOPT_ENCODING: + /* + * String to use at the value of Accept-Encoding header. 08/28/02 jhrg + */ + data->set.encoding = va_arg(param, char *); + break; + case CURLOPT_USERPWD: /* * user:password to use in the operation @@ -752,7 +828,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) * Progress callback function */ data->set.fprogress = va_arg(param, curl_progress_callback); - data->progress.callback = TRUE; /* no longer internal */ + if(data->set.fprogress) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + break; case CURLOPT_PROGRESSDATA: /* @@ -765,6 +845,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) * Password prompt callback */ data->set.fpasswd = va_arg(param, curl_passwd_callback); + /* + * if the callback provided is null, reset the default callback + */ + if(!data->set.fpasswd) + { + data->set.fpasswd = my_getpass; + } break; case CURLOPT_PASSWDDATA: /* @@ -790,12 +877,30 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) */ data->set.set_resume_from = va_arg(param, long); break; + case CURLOPT_DEBUGFUNCTION: + /* + * stderr write callback. + */ + data->set.fdebug = va_arg(param, curl_debug_callback); + /* + * if the callback provided is NULL, it'll use the default callback + */ + break; + case CURLOPT_DEBUGDATA: + /* + * Set to a void * that should receive all error writes. This + * defaults to CURLOPT_STDERR for normal operations. + */ + data->set.debugdata = va_arg(param, void *); + break; case CURLOPT_STDERR: /* * Set to a FILE * that should receive all error writes. This * defaults to stderr for normal operations. */ data->set.err = va_arg(param, FILE *); + if(!data->set.err) + data->set.err = stderr; break; case CURLOPT_HEADERFUNCTION: /* @@ -928,7 +1033,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) * Set CA info for SSL connection. Specify file name of the CA certificate */ data->set.ssl.CAfile = va_arg(param, char *); - data->set.ssl.CApath = NULL; /*This does not work on windows.*/ + break; + case CURLOPT_CAPATH: + /* + * Set CA path info for SSL connection. Specify directory name of the CA + * certificates which have been prepared using openssl c_rehash utility. + */ + /* This does not work on windows. */ + data->set.ssl.CApath = va_arg(param, char *); break; case CURLOPT_TELNETOPTIONS: /* @@ -936,9 +1048,49 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) */ data->set.telnet_options = va_arg(param, struct curl_slist *); break; + + case CURLOPT_BUFFERSIZE: + /* + * The application kindly asks for a differently sized receive buffer. + * If it seems reasonable, we'll use it. + */ + data->set.buffer_size = va_arg(param, long); + + if(data->set.buffer_size> (BUFSIZE -1 )) + data->set.buffer_size = 0; /* huge internal default */ + + break; + + case CURLOPT_NOSIGNAL: + /* + * The application asks not to set any signal() or alarm() handlers, + * even when using a timeout. + */ + data->set.no_signal = va_arg(param, long) ? TRUE : FALSE; + break; + + case CURLOPT_SHARE: + { + curl_share *set; + set = va_arg(param, curl_share *); + if(data->share) + data->share->dirty--; + + data->share = set; + data->share->dirty++; + } + break; + + case CURLOPT_PROXYTYPE: + /* + * Set proxy type. HTTP/SOCKS4/SOCKS5 + */ + data->set.proxytype = va_arg(param, long); + break; + default: /* unknown tag and its companion, just ignore: */ - return CURLE_READ_ERROR; /* correct this */ + return CURLE_FAILED_INIT; /* correct this */ } return CURLE_OK; } @@ -993,6 +1145,8 @@ CURLcode Curl_disconnect(struct connectdata *conn) free(conn->allocptr.uagent); if(conn->allocptr.userpwd) free(conn->allocptr.userpwd); + if(conn->allocptr.accept_encoding) + free(conn->allocptr.accept_encoding); if(conn->allocptr.rangeline) free(conn->allocptr.rangeline); if(conn->allocptr.ref) @@ -1026,7 +1180,7 @@ static bool SocketIsDead(int sock) FD_SET(sock,&check_set); to.tv_sec = 0; - to.tv_usec = 1; + to.tv_usec = 0; sval = select(sock + 1, &check_set, 0, 0, &to); if(sval == 0) @@ -1050,6 +1204,7 @@ ConnectionExists(struct SessionHandle *data, struct connectdata *check; for(i=0; i< data->state.numconnects; i++) { + bool match = FALSE; /* * Note that if we use a HTTP proxy, we check connections to that * proxy and not to the actual remote server. @@ -1070,7 +1225,6 @@ ConnectionExists(struct SessionHandle *data, if(strequal(needle->protostr, check->protostr) && strequal(needle->name, check->name) && (needle->remote_port == check->remote_port) ) { - bool dead; if(strequal(needle->protostr, "FTP")) { /* This is FTP, verify that we're using the same name and password as well */ @@ -1080,27 +1234,7 @@ ConnectionExists(struct SessionHandle *data, continue; } } - dead = SocketIsDead(check->firstsocket); - if(dead) { - /* - * Even though the connection seems to have passed away, we could - * still make an effort to get the name information, as we intend to - * connect to the same host again. - * - * This is now subject to discussion. What do you think? - */ - infof(data, "Connection %d seems to be dead!\n", i); - Curl_disconnect(check); /* disconnect resources */ - data->state.connects[i]=NULL; /* nothing here */ - - /* There's no need to continue search, because we only store - one connection for each unique set of identifiers */ - return FALSE; - } - - *usethis = check; - return TRUE; /* yes, we found one to use! */ - + match = TRUE; } } else { /* The requested needle connection is using a proxy, @@ -1109,9 +1243,26 @@ ConnectionExists(struct SessionHandle *data, strequal(needle->proxyhost, check->proxyhost) && needle->port == check->port) { /* This is the same proxy connection, use it! */ - *usethis = check; - return TRUE; + match = TRUE; + } + } + + if(match) { + bool dead = SocketIsDead(check->firstsocket); + if(dead) { + /* + */ + infof(data, "Connection %d seems to be dead!\n", i); + Curl_disconnect(check); /* disconnect resources */ + data->state.connects[i]=NULL; /* nothing here */ + + /* There's no need to continue searching, because we only store + one connection for each unique set of identifiers */ + return FALSE; } + + *usethis = check; + return TRUE; /* yes, we found one to use! */ } } return FALSE; /* no matching connecting exists */ @@ -1213,7 +1364,197 @@ ConnectionStore(struct SessionHandle *data, return i; } -static CURLcode ConnectPlease(struct connectdata *conn) +/* + * This function logs in to a SOCKS5 proxy and sends the specifies the final + * desitination server. + */ +static int handleSock5Proxy( + const char *proxy_name, + const char *proxy_password, + struct connectdata *conn, + int sock) +{ + unsigned char socksreq[600]; /* room for large user/pw (255 max each) */ + int actualread; + int written; + CURLcode result; + + Curl_nonblock(sock, FALSE); + + socksreq[0] = 5; /* version */ + socksreq[1] = (char)(proxy_name[0] ? 2 : 1); /* number of methods (below) */ + socksreq[2] = 0; /* no authentication */ + socksreq[3] = 2; /* username/password */ + + result = Curl_write(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]), + &written); + if ((result != CURLE_OK) || (written != (2 + (int)socksreq[1]))) { + failf(conn->data, "Unable to send initial SOCKS5 request."); + return 1; + } + + result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread); + if ((result != CURLE_OK) || (actualread != 2)) { + failf(conn->data, "Unable to receive initial SOCKS5 response."); + return 1; + } + + if (socksreq[0] != 5) { + failf(conn->data, "Received invalid version in initial SOCKS5 response."); + return 1; + } + if (socksreq[1] == 0) { + /* Nothing to do, no authentication needed */ + ; + } + else if (socksreq[1] == 2) { + /* Needs user name and password */ + int userlen, pwlen, len; + + userlen = strlen(proxy_name); + pwlen = strlen(proxy_password); + + /* username/password request looks like + * +----+------+----------+------+----------+ + * |VER | ULEN | UNAME | PLEN | PASSWD | + * +----+------+----------+------+----------+ + * | 1 | 1 | 1 to 255 | 1 | 1 to 255 | + * +----+------+----------+------+----------+ + */ + len = 0; + socksreq[len++] = 1; /* username/pw subnegotiation version */ + socksreq[len++] = (char) userlen; + memcpy(socksreq + len, proxy_name, (int) userlen); + len += userlen; + socksreq[len++] = (char) pwlen; + memcpy(socksreq + len, proxy_password, (int) pwlen); + len += pwlen; + + result = Curl_write(conn, sock, (char *)socksreq, len, &written); + if ((result != CURLE_OK) || (len != written)) { + failf(conn->data, "Failed to send SOCKS5 sub-negotiation request."); + return 1; + } + + result=Curl_read(conn, sock, (char *)socksreq, 2, &actualread); + if ((result != CURLE_OK) || (actualread != 2)) { + failf(conn->data, "Unable to receive SOCKS5 sub-negotiation response."); + return 1; + } + + if ((socksreq[0] != 5) || /* version */ + (socksreq[1] != 0)) { /* status */ + failf(conn->data, "User was rejected by the SOCKS5 server (%d %d).", + socksreq[0], socksreq[1]); + return 1; + } + + /* Everything is good so far, user was authenticated! */ + } + else { + /* error */ + if (socksreq[1] == 1) { + failf(conn->data, + "SOCKS5 GSSAPI per-message authentication is not supported."); + return 1; + } + else if (socksreq[1] == 255) { + if (proxy_name[0] == 0) { + failf(conn->data, + "No authentication method was acceptable. (It is quite likely" + " that the SOCKS5 server wanted a username/password, since none" + " was supplied to the server on this connection.)"); + } + else { + failf(conn->data, "No authentication method was acceptable."); + } + return 1; + } + else { + failf(conn->data, + "Undocumented SOCKS5 mode attempted to be used by server."); + return 1; + } + } + + /* Authentication is complete, now specify destination to the proxy */ + socksreq[0] = 5; /* version (SOCKS5) */ + socksreq[1] = 1; /* connect */ + socksreq[2] = 0; /* must be zero */ + socksreq[3] = 1; /* IPv4 = 1 */ + + { +#ifndef ENABLE_IPV6 + struct Curl_dns_entry *dns; + Curl_addrinfo *hp=NULL; + dns = Curl_resolv(conn->data, conn->hostname, conn->remote_port); + /* + * We cannot use 'hostent' as a struct that Curl_resolv() returns. It + * returns a Curl_addrinfo pointer that may not always look the same. + */ + if(dns) + hp=dns->addr; + if (hp && hp->h_addr_list[0]) { + socksreq[4] = ((char*)hp->h_addr_list[0])[0]; + socksreq[5] = ((char*)hp->h_addr_list[0])[1]; + socksreq[6] = ((char*)hp->h_addr_list[0])[2]; + socksreq[7] = ((char*)hp->h_addr_list[0])[3]; + + Curl_resolv_unlock(dns); /* not used anymore from now on */ + } + else { + failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.", + conn->hostname); + return 1; + } +#else + failf(conn->data, + "%s:%d has an internal error an needs to be fixed to work", + __FILE__, __LINE__); + return 1; +#endif + } + + *((unsigned short*)&socksreq[8]) = htons(conn->remote_port); + + { + const int packetsize = 10; + + result = Curl_write(conn, sock, (char *)socksreq, packetsize, &written); + if ((result != CURLE_OK) || (written != packetsize)) { + failf(conn->data, "Failed to send SOCKS5 connect request."); + return 1; + } + + result = Curl_read(conn, sock, (char *)socksreq, packetsize, &actualread); + if ((result != CURLE_OK) || (actualread != packetsize)) { + failf(conn->data, "Failed to receive SOCKS5 connect request ack."); + return 1; + } + + if (socksreq[0] != 5) { /* version */ + failf(conn->data, + "SOCKS5 reply has wrong version, version should be 5."); + return 1; + } + if (socksreq[1] != 0) { /* Anything besides 0 is an error */ + failf(conn->data, + "Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)", + (unsigned char)socksreq[4], (unsigned char)socksreq[5], + (unsigned char)socksreq[6], (unsigned char)socksreq[7], + (unsigned int)ntohs(*(unsigned short*)(&socksreq[8])), + socksreq[1]); + return 1; + } + } + + Curl_nonblock(sock, TRUE); + return 0; /* Proxy was successful! */ +} + +static CURLcode ConnectPlease(struct connectdata *conn, + struct Curl_dns_entry *hostaddr, + bool *connected) { CURLcode result; Curl_ipconnect *addr; @@ -1222,28 +1563,130 @@ static CURLcode ConnectPlease(struct connectdata *conn) * Connect to server/proxy *************************************************************/ result= Curl_connecthost(conn, - conn->hostaddr, + hostaddr, conn->port, &conn->firstsocket, - &addr); + &addr, + connected); if(CURLE_OK == result) { /* All is cool, then we store the current information from the hostaddr struct to the serv_addr, as it might be needed later. The address returned from the function above is crucial here. */ + conn->connect_addr = hostaddr; + #ifdef ENABLE_IPV6 conn->serv_addr = addr; #else memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr)); memcpy((char *)&(conn->serv_addr.sin_addr), (struct in_addr *)addr, sizeof(struct in_addr)); - conn->serv_addr.sin_family = conn->hostaddr->h_addrtype; - conn->serv_addr.sin_port = htons(conn->port); + conn->serv_addr.sin_family = hostaddr->addr->h_addrtype; + conn->serv_addr.sin_port = htons((unsigned short)conn->port); #endif + + if (conn->data->set.proxytype == CURLPROXY_SOCKS5) { + return handleSock5Proxy(conn->data->state.proxyuser, + conn->data->state.proxypasswd, + conn, + conn->firstsocket) ? + CURLE_COULDNT_CONNECT : CURLE_OK; + } + else if (conn->data->set.proxytype == CURLPROXY_HTTP) { + /* do nothing here. handled later. */ + } + else { + failf(conn->data, "unknown proxytype option given"); + return CURLE_COULDNT_CONNECT; + } } return result; } +static void verboseconnect(struct connectdata *conn, + struct Curl_dns_entry *dns) +{ +#ifdef HAVE_INET_NTOA_R + char ntoa_buf[64]; +#endif + struct SessionHandle *data = conn->data; + + /* Figure out the ip-number and display the first host name it shows: */ +#ifdef ENABLE_IPV6 + (void)dns; /* not used in the IPv6 enabled version */ + { + char hbuf[NI_MAXHOST]; +#ifdef NI_WITHSCOPEID + const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; +#else + const int niflags = NI_NUMERICHOST; +#endif + struct addrinfo *ai = conn->serv_addr; + + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, + niflags)) { + snprintf(hbuf, sizeof(hbuf), "?"); + } + if (ai->ai_canonname) { + infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf, + conn->port); + } else { + infof(data, "Connected to %s port %d\n", hbuf, conn->port); + } + } +#else + { + Curl_addrinfo *hostaddr=dns->addr; + struct in_addr in; + (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr)); + infof(data, "Connected to %s (%s) port %d\n", + hostaddr?hostaddr->h_name:"", +#if defined(HAVE_INET_NTOA_R) + inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)), +#else + inet_ntoa(in), +#endif + conn->port); + } +#endif +} + +/* + * We have discovered that the TCP connection has been successful, we can now + * proceed with some action. + * + * If we're using the multi interface, this host address pointer is most + * likely NULL at this point as we can't keep the resolved info around. This + * may call for some reworking, like a reference counter in the struct or + * something. The hostaddr is not used for very much though, we have the + * 'serv_addr' field in the connectdata struct for most of it. + */ +CURLcode Curl_protocol_connect(struct connectdata *conn, + struct Curl_dns_entry *hostaddr) +{ + struct SessionHandle *data = conn->data; + CURLcode result=CURLE_OK; + + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ + + if(data->set.verbose) + verboseconnect(conn, hostaddr); + + if(conn->curl_connect) { + /* is there a protocol-specific connect() procedure? */ + + /* set start time here for timeout purposes in the + * connect procedure, it is later set again for the + * progress meter purpose */ + conn->now = Curl_tvnow(); + + /* Call the protocol-specific connect function */ + result = conn->curl_connect(conn); + } + + return result; /* pass back status */ +} + static CURLcode CreateConnection(struct SessionHandle *data, struct connectdata **in_connect) { @@ -1253,18 +1696,16 @@ static CURLcode CreateConnection(struct SessionHandle *data, char resumerange[40]=""; struct connectdata *conn; struct connectdata *conn_temp; - char endbracket; int urllen; -#ifdef HAVE_INET_NTOA_R - char ntoa_buf[64]; -#endif + struct Curl_dns_entry *hostaddr; #ifdef HAVE_ALARM - unsigned int prev_alarm; + unsigned int prev_alarm=0; #endif + char endbracket; #ifdef HAVE_SIGACTION struct sigaction keep_sigact; /* store the old struct here */ - bool keep_copysig; /* did copy it? */ + bool keep_copysig=FALSE; /* did copy it? */ #else #ifdef HAVE_SIGNAL void *keep_sigact; /* store the old handler here */ @@ -1301,16 +1742,18 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->firstsocket = -1; /* no file descriptor */ conn->secondarysocket = -1; /* no file descriptor */ conn->connectindex = -1; /* no index */ - conn->bits.httpproxy = data->change.proxy?TRUE:FALSE; /* proxy-or-not */ + conn->bits.httpproxy = (data->change.proxy && *data->change.proxy && + (data->set.proxytype == CURLPROXY_HTTP))? + TRUE:FALSE; /* http proxy or not */ conn->bits.use_range = data->set.set_range?TRUE:FALSE; /* range status */ - conn->range = data->set.set_range; /* clone the range setting */ + conn->range = data->set.set_range; /* clone the range setting */ conn->resume_from = data->set.set_resume_from; /* inherite resume_from */ /* Default protocol-independent behavior doesn't support persistant connections, so we set this to force-close. Protocols that support this need to set this to FALSE in their "curl_do" functions. */ conn->bits.close = TRUE; - + /* inherite initial knowledge from the data struct */ conn->bits.user_passwd = data->set.userpwd?1:0; conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0; @@ -1321,6 +1764,20 @@ static CURLcode CreateConnection(struct SessionHandle *data, /* Store creation time to help future close decision making */ conn->created = Curl_tvnow(); + /* Set the start time temporary to this creation time to allow easier + timeout checks before the transfer has started for real. The start time + is later set "for real" using Curl_pgrsStartNow(). */ + conn->data->progress.start = conn->created; + + conn->bits.upload_chunky = + ((conn->protocol&PROT_HTTP) && + data->set.upload && + (data->set.infilesize == -1) && + (data->set.httpversion != CURL_HTTP_VERSION_1_0))? + /* HTTP, upload, unknown file size and not HTTP 1.0 */ + TRUE: + /* else, no chunky upload */ + FALSE; /*********************************************************** * We need to allocate memory to store the path in. We get the size of the @@ -1410,22 +1867,25 @@ static CURLcode CreateConnection(struct SessionHandle *data, * is based on the first letters of the server name. */ - if(strnequal(conn->gname, "FTP", 3)) { + /* Note: if you add a new protocol, please update the list in + * lib/version.c too! */ + + if(checkprefix("FTP", conn->gname)) { strcpy(conn->protostr, "ftp"); } - else if(strnequal(conn->gname, "GOPHER", 6)) + else if(checkprefix("GOPHER", conn->gname)) strcpy(conn->protostr, "gopher"); #ifdef USE_SSLEAY - else if(strnequal(conn->gname, "HTTPS", 5)) + else if(checkprefix("HTTPS", conn->gname)) strcpy(conn->protostr, "https"); - else if(strnequal(conn->gname, "FTPS", 4)) + else if(checkprefix("FTPS", conn->gname)) strcpy(conn->protostr, "ftps"); #endif /* USE_SSLEAY */ - else if(strnequal(conn->gname, "TELNET", 6)) + else if(checkprefix("TELNET", conn->gname)) strcpy(conn->protostr, "telnet"); - else if (strnequal(conn->gname, "DICT", sizeof("DICT")-1)) + else if (checkprefix("DICT", conn->gname)) strcpy(conn->protostr, "DICT"); - else if (strnequal(conn->gname, "LDAP", sizeof("LDAP")-1)) + else if (checkprefix("LDAP", conn->gname)) strcpy(conn->protostr, "LDAP"); else { strcpy(conn->protostr, "http"); @@ -1437,32 +1897,12 @@ static CURLcode CreateConnection(struct SessionHandle *data, buf = data->state.buffer; /* this is our buffer */ - /************************************************************* - * Take care of user and password authentication stuff - *************************************************************/ - - if(conn->bits.user_passwd && !data->set.use_netrc) { - data->state.user[0] =0; - data->state.passwd[0]=0; - - if(*data->set.userpwd != ':') { - /* the name is given, get user+password */ - sscanf(data->set.userpwd, "%127[^:]:%127[^\n]", - data->state.user, data->state.passwd); - } - else - /* no name given, get the password only */ - sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd); - - /* check for password, if no ask for one */ - if( !data->state.passwd[0] ) { - if(!data->set.fpasswd || - data->set.fpasswd(data->set.passwd_client, - "password:", data->state.passwd, - sizeof(data->state.passwd))) - return CURLE_BAD_PASSWORD_ENTERED; - } - } + /* + * So if the URL was A://B/C, + * conn->protostr is A + * conn->gname is B + * conn->path is /C + */ /************************************************************* * Take care of proxy authentication stuff @@ -1482,12 +1922,13 @@ static CURLcode CreateConnection(struct SessionHandle *data, /* check for password, if no ask for one */ if( !data->state.proxypasswd[0] ) { - if(!data->set.fpasswd || - data->set.fpasswd( data->set.passwd_client, - "proxy password:", - data->state.proxypasswd, - sizeof(data->state.proxypasswd))) + if(data->set.fpasswd( data->set.passwd_client, + "proxy password:", + data->state.proxypasswd, + sizeof(data->state.proxypasswd))) { + failf(data, "Bad password from password callback"); return CURLE_BAD_PASSWORD_ENTERED; + } } } @@ -1537,10 +1978,17 @@ static CURLcode CreateConnection(struct SessionHandle *data, nope=no_proxy?strtok_r(no_proxy, ", ", &no_proxy_tok_buf):NULL; while(nope) { - if(strlen(nope) <= strlen(conn->name)) { + unsigned int namelen; + char *endptr = strchr(conn->name, ':'); + if(endptr) + namelen=endptr-conn->name; + else + namelen=strlen(conn->name); + + if(strlen(nope) <= namelen) { char *checkn= - conn->name + strlen(conn->name) - strlen(nope); - if(strnequal(nope, checkn, strlen(nope))) { + conn->name + namelen - strlen(nope); + if(checkprefix(nope, checkn)) { /* no proxy for this host! */ break; } @@ -1622,6 +2070,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->protocol &= ~PROT_MISSING; /* switch that one off again */ } +#ifndef CURL_DISABLE_HTTP /************************************************************ * RESUME on a HTTP page is a tricky business. First, let's just check that * 'range' isn't used, then set the range parameter and leave the resume as @@ -1640,22 +2089,29 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->bits.use_range = 1; /* switch on range usage */ } } - +#endif /************************************************************* * Setup internals depending on protocol *************************************************************/ if (strequal(conn->protostr, "HTTP")) { +#ifndef CURL_DISABLE_HTTP conn->port = (data->set.use_port && data->state.allow_port)? data->set.use_port:PORT_HTTP; conn->remote_port = PORT_HTTP; conn->protocol |= PROT_HTTP; conn->curl_do = Curl_http; + conn->curl_do_more = NULL; conn->curl_done = Curl_http_done; conn->curl_connect = Curl_http_connect; +#else + failf(data, LIBCURL_NAME + " was built with HTTP disabled, http: not supported!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif } else if (strequal(conn->protostr, "HTTPS")) { -#ifdef USE_SSLEAY +#if defined(USE_SSLEAY) && !defined(CURL_DISABLE_HTTP) conn->port = (data->set.use_port && data->state.allow_port)? data->set.use_port:PORT_HTTPS; @@ -1663,6 +2119,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->protocol |= PROT_HTTP|PROT_HTTPS|PROT_SSL; conn->curl_do = Curl_http; + conn->curl_do_more = NULL; conn->curl_done = Curl_http_done; conn->curl_connect = Curl_http_connect; @@ -1673,6 +2130,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, #endif /* !USE_SSLEAY */ } else if (strequal(conn->protostr, "GOPHER")) { +#ifndef CURL_DISABLE_GOPHER conn->port = (data->set.use_port && data->state.allow_port)? data->set.use_port:PORT_GOPHER; conn->remote_port = PORT_GOPHER; @@ -1684,10 +2142,18 @@ static CURLcode CreateConnection(struct SessionHandle *data, } conn->protocol |= PROT_GOPHER; conn->curl_do = Curl_http; + conn->curl_do_more = NULL; conn->curl_done = Curl_http_done; +#else + failf(data, LIBCURL_NAME + " was built with GOPHER disabled, gopher: not supported!"); +#endif } else if(strequal(conn->protostr, "FTP") || strequal(conn->protostr, "FTPS")) { + +/* MN 06/07/02 */ +#ifndef CURL_DISABLE_FTP char *type; if(strequal(conn->protostr, "FTPS")) { @@ -1706,6 +2172,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->protocol |= PROT_FTP; if(data->change.proxy && + *data->change.proxy && !data->set.tunnel_thru_httpproxy) { /* Unless we have asked to tunnel ftp operations through the proxy, we switch and use HTTP operations only */ @@ -1715,11 +2182,17 @@ static CURLcode CreateConnection(struct SessionHandle *data, failf(data, "ftps does not work through http proxy!"); return CURLE_UNSUPPORTED_PROTOCOL; } +#ifndef CURL_DISABLE_HTTP conn->curl_do = Curl_http; conn->curl_done = Curl_http_done; +#else + failf(data, "FTP over http proxy requires HTTP support built-in!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif } else { conn->curl_do = Curl_ftp; + conn->curl_do_more = Curl_ftp_nextconnect; conn->curl_done = Curl_ftp_done; conn->curl_connect = Curl_ftp_connect; conn->curl_disconnect = Curl_ftp_disconnect; @@ -1735,7 +2208,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, } if(type) { char command; - *type=0; + *type=0; /* it was in the middle of the hostname */ command = toupper(type[6]); switch(command) { case 'A': /* ASCII mode */ @@ -1751,8 +2224,16 @@ static CURLcode CreateConnection(struct SessionHandle *data, break; } } + +/* MN 06/07/02 */ +#else /* CURL_DISABLE_FTP */ + failf(data, LIBCURL_NAME + " was built with FTP disabled, ftp/ftps: not supported!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif } else if(strequal(conn->protostr, "TELNET")) { +#ifndef CURL_DISABLE_TELNET /* telnet testing factory */ conn->protocol |= PROT_TELNET; @@ -1761,24 +2242,39 @@ static CURLcode CreateConnection(struct SessionHandle *data, conn->remote_port = PORT_TELNET; conn->curl_do = Curl_telnet; conn->curl_done = Curl_telnet_done; +#else + failf(data, LIBCURL_NAME + " was built with TELNET disabled!"); +#endif } else if (strequal(conn->protostr, "DICT")) { +#ifndef CURL_DISABLE_DICT conn->protocol |= PROT_DICT; conn->port = (data->set.use_port && data->state.allow_port)? data->set.use_port:PORT_DICT; conn->remote_port = PORT_DICT; conn->curl_do = Curl_dict; conn->curl_done = NULL; /* no DICT-specific done */ +#else + failf(data, LIBCURL_NAME + " was built with DICT disabled!"); +#endif } else if (strequal(conn->protostr, "LDAP")) { +#ifndef CURL_DISABLE_LDAP conn->protocol |= PROT_LDAP; conn->port = (data->set.use_port && data->state.allow_port)? data->set.use_port:PORT_LDAP; conn->remote_port = PORT_LDAP; conn->curl_do = Curl_ldap; conn->curl_done = NULL; /* no LDAP-specific done */ +#else + failf(data, LIBCURL_NAME + " was built with LDAP disabled!"); +#endif } else if (strequal(conn->protostr, "FILE")) { +#ifndef CURL_DISABLE_FILE conn->protocol |= PROT_FILE; conn->curl_do = Curl_file; @@ -1795,6 +2291,10 @@ static CURLcode CreateConnection(struct SessionHandle *data, } return result; +#else + failf(data, LIBCURL_NAME + " was built with FILE disabled!"); +#endif } else { /* We fell through all checks and thus we don't support the specified @@ -1804,84 +2304,6 @@ static CURLcode CreateConnection(struct SessionHandle *data, } /************************************************************* - * .netrc scanning coming up - *************************************************************/ - if(data->set.use_netrc) { - if(Curl_parsenetrc(conn->hostname, - data->state.user, - data->state.passwd)) { - infof(data, "Couldn't find host %s in the .netrc file, using defaults", - conn->hostname); - } - else - conn->bits.user_passwd = 1; /* enable user+password */ - - /* weather we failed or not, we don't know which fields that were filled - in anyway */ - if(!data->state.user[0]) - strcpy(data->state.user, CURL_DEFAULT_USER); - if(!data->state.passwd[0]) - strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD); - } - else if(!(conn->bits.user_passwd) && - (conn->protocol & (PROT_FTP|PROT_HTTP)) ) { - /* This is a FTP or HTTP URL, and we haven't got the user+password in - * the extra parameter, we will now try to extract the possible - * user+password pair in a string like: - * ftp://user:password@ftp.my.site:8021/README */ - char *ptr=NULL; /* assign to remove possible warnings */ - if((ptr=strchr(conn->name, '@'))) { - /* there's a user+password given here, to the left of the @ */ - - data->state.user[0] =0; - data->state.passwd[0]=0; - - if(*conn->name != ':') { - /* the name is given, get user+password */ - sscanf(conn->name, "%127[^:@]:%127[^@]", - data->state.user, data->state.passwd); - } - else - /* no name given, get the password only */ - sscanf(conn->name+1, "%127[^@]", data->state.passwd); - - if(data->state.user[0]) { - char *newname=curl_unescape(data->state.user, 0); - if(strlen(newname) < sizeof(data->state.user)) { - strcpy(data->state.user, newname); - } - /* if the new name is longer than accepted, then just use - the unconverted name, it'll be wrong but what the heck */ - free(newname); - } - - /* check for password, if no ask for one */ - if( !data->state.passwd[0] ) { - if(!data->set.fpasswd || - data->set.fpasswd(data->set.passwd_client, - "password:", data->state.passwd, - sizeof(data->state.passwd))) - return CURLE_BAD_PASSWORD_ENTERED; - } - else { - /* we have a password found in the URL, decode it! */ - char *newpasswd=curl_unescape(data->state.passwd, 0); - if(strlen(newpasswd) < sizeof(data->state.passwd)) { - strcpy(data->state.passwd, newpasswd); - } - free(newpasswd); - } - - conn->name = ++ptr; - conn->bits.user_passwd=TRUE; /* enable user+password */ - } - else { - strcpy(data->state.user, CURL_DEFAULT_USER); - strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD); - } - } - - /************************************************************* * Figure out the remote port number * * No matter if we use a proxy or not, we have to figure out the remote @@ -1889,32 +2311,48 @@ static CURLcode CreateConnection(struct SessionHandle *data, * * To be able to detect port number flawlessly, we must not confuse them * IPv6-specified addresses in the [0::1] style. (RFC2732) + * + * The conn->name is currently [user:passwd@]host[:port] where host could + * be a hostname, IPv4 address or IPv6 address. *************************************************************/ - if((1 == sscanf(conn->name, "[%*39[0-9a-fA-F:.]%c", &endbracket)) && (']' == endbracket)) { - /* This is a (IPv6-style) specified IP-address. We support _any_ - IP within brackets to be really generic. */ - conn->name++; /* pass the starting bracket */ + /* this is a RFC2732-style specified IP-address */ + conn->bits.ipv6_ip = TRUE; + conn->name++; /* pass the starting bracket */ + conn->hostname++; tmp = strchr(conn->name, ']'); *tmp = 0; /* zero terminate */ - tmp++; /* pass the ending bracket */ if(':' != *tmp) tmp = NULL; /* no port number available */ } - else { - /* traditional IPv4-style port-extracting */ - tmp = strchr(conn->name, ':'); - } + else + tmp = strrchr(conn->name, ':'); if (tmp) { - *tmp++ = '\0'; /* cut off the name there */ - conn->remote_port = atoi(tmp); + char *rest; + unsigned long port; + + port=strtoul(tmp+1, &rest, 10); /* Port number must be decimal */ + + if (rest != (tmp+1) && *rest == '\0') { + /* The colon really did have only digits after it, + * so it is either a port number or a mistake */ + + if (port > 0xffff) { /* Single unix standard says port numbers are + * 16 bits long */ + failf(data, "Port number too large: %lu", port); + return CURLE_URL_MALFORMAT; + } + + *tmp = '\0'; /* cut off the name there */ + conn->remote_port = (unsigned short)port; + } } - if(data->change.proxy) { + if(data->change.proxy && *data->change.proxy) { /* If this is supposed to use a proxy, we need to figure out the proxy host name name, so that we can re-use an existing connection that may exist registered to the same proxy host. */ @@ -1966,6 +2404,137 @@ static CURLcode CreateConnection(struct SessionHandle *data, } /************************************************************* + * Take care of user and password authentication stuff + *************************************************************/ + + /* + * Inputs: data->set.userpwd (CURLOPT_USERPWD) + * data->set.fpasswd (CURLOPT_PASSWDFUNCTION) + * data->set.use_netrc (CURLOPT_NETRC) + * conn->hostname + * netrc file + * hard-coded defaults + * + * Outputs: (almost :- all currently undefined) + * conn->bits.user_passwd - non-zero if non-default passwords exist + * conn->state.user - non-zero length if defined + * conn->state.passwd - ditto + * conn->hostname - remove user name and password + */ + + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->hostname is at most + * [user[:password]]@]hostname + * + * We need somewhere to put the embedded details, so do that first. + */ + + data->state.user[0] =0; /* to make everything well-defined */ + data->state.passwd[0]=0; + + if (conn->protocol & (PROT_FTP|PROT_HTTP)) { + /* This is a FTP or HTTP URL, we will now try to extract the possible + * user+password pair in a string like: + * ftp://user:password@ftp.my.site:8021/README */ + char *ptr=strchr(conn->name, '@'); + char *userpass = conn->name; + if(ptr != NULL) { + /* there's a user+password given here, to the left of the @ */ + + conn->name = conn->hostname = ++ptr; + + /* So the hostname is sane. Only bother interpreting the + * results if we could care. It could still be wasted + * work because it might be overtaken by the programmatically + * set user/passwd, but doing that first adds more cases here :-( + */ + + if (data->set.use_netrc != CURL_NETRC_REQUIRED) { + /* We could use the one in the URL */ + + conn->bits.user_passwd = 1; /* enable user+password */ + + if(*userpass != ':') { + /* the name is given, get user+password */ + sscanf(userpass, "%127[^:@]:%127[^@]", + data->state.user, data->state.passwd); + } + else + /* no name given, get the password only */ + sscanf(userpass, ":%127[^@]", data->state.passwd); + + if(data->state.user[0]) { + char *newname=curl_unescape(data->state.user, 0); + if(strlen(newname) < sizeof(data->state.user)) { + strcpy(data->state.user, newname); + } + /* if the new name is longer than accepted, then just use + the unconverted name, it'll be wrong but what the heck */ + free(newname); + } + if (data->state.passwd[0]) { + /* we have a password found in the URL, decode it! */ + char *newpasswd=curl_unescape(data->state.passwd, 0); + if(strlen(newpasswd) < sizeof(data->state.passwd)) { + strcpy(data->state.passwd, newpasswd); + } + free(newpasswd); + } + } + } + } + + /* Programmatically set password: + * - always applies, if available + * - takes precedence over the values we just set above + * so scribble it over the top. + * User-supplied passwords are assumed not to need unescaping. + * + * user_password is set in "inherite initial knowledge' above, + * so it doesn't have to be set in this block + */ + if (data->set.userpwd != NULL) { + if(*data->set.userpwd != ':') { + /* the name is given, get user+password */ + sscanf(data->set.userpwd, "%127[^:]:%127[^\n]", + data->state.user, data->state.passwd); + } + else + /* no name given, get the password only */ + sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd); + } + + if (data->set.use_netrc != CURL_NETRC_IGNORED && + data->state.passwd[0] == '\0' ) { /* need passwd */ + if(Curl_parsenetrc(conn->hostname, + data->state.user, + data->state.passwd)) { + infof(data, "Couldn't find host %s in the .netrc file, using defaults", + conn->hostname); + } else + conn->bits.user_passwd = 1; /* enable user+password */ + } + + /* if we have a user but no password, ask for one */ + if(conn->bits.user_passwd && + !data->state.passwd[0] ) { + if(data->set.fpasswd(data->set.passwd_client, + "password:", data->state.passwd, + sizeof(data->state.passwd))) + return CURLE_BAD_PASSWORD_ENTERED; + } + + /* So we could have a password but no user; that's just too bad. */ + + /* If our protocol needs a password and we have none, use the defaults */ + if ( (conn->protocol & (PROT_FTP|PROT_HTTP)) && + !conn->bits.user_passwd) { + strcpy(data->state.user, CURL_DEFAULT_USER); + strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD); + /* This is the default password, so DON'T set conn->bits.user_passwd */ + } + + /************************************************************* * Check the current list of connections to see if we can * re-use an already existing one or if we have to create a * new one. @@ -1988,6 +2557,10 @@ static CURLcode CreateConnection(struct SessionHandle *data, free(old_conn->proxyhost); conn = conn_temp; /* use this connection from now on */ + /* If we speak over a proxy, we need to copy the host name too, as it + might be another remote host even when re-using a connection */ + strcpy(conn->gname, old_conn->gname); /* safe strcpy() */ + /* we need these pointers if we speak over a proxy */ conn->hostname = conn->gname; conn->name = &conn->gname[old_conn->name - old_conn->gname]; @@ -2044,7 +2617,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, /************************************************************* * Set timeout if that is being used *************************************************************/ - if(data->set.timeout || data->set.connecttimeout) { + if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) { /************************************************************* * Set signal handler to catch SIGALRM * Store the old value to be able to set it back later! @@ -2089,33 +2662,31 @@ static CURLcode CreateConnection(struct SessionHandle *data, /************************************************************* * Resolve the name of the server or proxy *************************************************************/ - if(!data->change.proxy) { + if(conn->bits.reuse) { + /* re-used connection, no resolving is necessary */ + hostaddr = NULL; + } + else if(!data->change.proxy || !*data->change.proxy) { /* If not connecting via a proxy, extract the port from the URL, if it is * there, thus overriding any defaults that might have been set above. */ conn->port = conn->remote_port; /* it is the same port */ /* Resolve target host right on */ - if(!conn->hostaddr) { - /* it might already be set if reusing a connection */ - conn->hostaddr = Curl_resolv(data, conn->name, conn->port, - &conn->hostent_buf); - } - if(!conn->hostaddr) { + hostaddr = Curl_resolv(data, conn->name, conn->port); + + if(!hostaddr) { failf(data, "Couldn't resolve host '%s'", conn->name); result = CURLE_COULDNT_RESOLVE_HOST; /* don't return yet, we need to clean up the timeout first */ } } - else if(!conn->hostaddr) { - /* This is a proxy that hasn't been resolved yet. It may be resolved - if we're reusing an existing connection. */ + else { + /* This is a proxy that hasn't been resolved yet. */ /* resolve proxy */ - /* it might already be set if reusing a connection */ - conn->hostaddr = Curl_resolv(data, conn->proxyhost, conn->port, - &conn->hostent_buf); + hostaddr = Curl_resolv(data, conn->proxyhost, conn->port); - if(!conn->hostaddr) { + if(!hostaddr) { failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost); result = CURLE_COULDNT_RESOLVE_PROXY; /* don't return yet, we need to clean up the timeout first */ @@ -2123,7 +2694,7 @@ static CURLcode CreateConnection(struct SessionHandle *data, } Curl_pgrsTime(data, TIMER_NAMELOOKUP); #ifdef HAVE_ALARM - if(data->set.timeout || data->set.connecttimeout) { + if((data->set.timeout || data->set.connecttimeout) && !data->set.no_signal) { #ifdef HAVE_SIGACTION if(keep_copysig) { /* we got a struct as it looked before, now put that one back nice @@ -2185,7 +2756,8 @@ static CURLcode CreateConnection(struct SessionHandle *data, * Send user-agent to HTTP proxies even if the target protocol * isn't HTTP. *************************************************************/ - if((conn->protocol&PROT_HTTP) || data->change.proxy) { + if((conn->protocol&PROT_HTTP) || + (data->change.proxy && *data->change.proxy)) { if(data->set.useragent) { if(conn->allocptr.uagent) free(conn->allocptr.uagent); @@ -2194,68 +2766,36 @@ static CURLcode CreateConnection(struct SessionHandle *data, } } - if(-1 == conn->firstsocket) { - /* Connect only if not already connected! */ - result = ConnectPlease(conn); - if(CURLE_OK != result) - return result; - - if(conn->curl_connect) { - /* is there a connect() procedure? */ - - /* set start time here for timeout purposes in the - * connect procedure, it is later set again for the - * progress meter purpose */ - conn->now = Curl_tvnow(); - - /* Call the protocol-specific connect function */ - result = conn->curl_connect(conn); - if(result != CURLE_OK) - return result; /* pass back errors */ - } + if(data->set.encoding) { + if(conn->allocptr.accept_encoding) + free(conn->allocptr.accept_encoding); + conn->allocptr.accept_encoding = + aprintf("Accept-Encoding: %s\015\012", data->set.encoding); } - Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected */ - - conn->now = Curl_tvnow(); /* time this *after* the connect is done */ conn->bytecount = 0; conn->headerbytecount = 0; - /* Figure out the ip-number and display the first host name it shows: */ -#ifdef ENABLE_IPV6 - { - char hbuf[NI_MAXHOST]; -#ifdef NI_WITHSCOPEID - const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; -#else - const int niflags = NI_NUMERICHOST; -#endif - struct addrinfo *ai = conn->serv_addr; + if(-1 == conn->firstsocket) { + bool connected; - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, - niflags)) { - snprintf(hbuf, sizeof(hbuf), "?"); - } - if (ai->ai_canonname) { - infof(data, "Connected to %s (%s) port %d\n", ai->ai_canonname, hbuf, - conn->port); - } else { - infof(data, "Connected to %s port %d\n", hbuf, conn->port); - } + /* Connect only if not already connected! */ + result = ConnectPlease(conn, hostaddr, &connected); + + if(connected) + result = Curl_protocol_connect(conn, hostaddr); + + if(CURLE_OK != result) + return result; } -#else - { - struct in_addr in; - (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr)); - infof(data, "Connected to %s (%s)\n", conn->hostaddr->h_name, -#if defined(HAVE_INET_NTOA_R) - inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)) -#else - inet_ntoa(in) -#endif - ); + else { + Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */ + if(data->set.verbose) + verboseconnect(conn, hostaddr); } -#endif + + conn->now = Curl_tvnow(); /* time this *after* the connect is done, we + set this here perhaps a second time */ #ifdef __EMX__ /* 20000330 mgs @@ -2293,7 +2833,6 @@ CURLcode Curl_connect(struct SessionHandle *data, return code; } - CURLcode Curl_done(struct connectdata *conn) { struct SessionHandle *data=conn->data; @@ -2311,7 +2850,16 @@ CURLcode Curl_done(struct connectdata *conn) free(conn->newurl); conn->newurl = NULL; } - + + if(conn->connect_addr) + Curl_resolv_unlock(conn->connect_addr); /* done with this */ + +#if defined(MALLOCDEBUG) && defined(AGGRESIVE_TEST) + /* scan for DNS cache entries still marked as in use */ + Curl_hash_apply(data->hostcache, + NULL, Curl_scan_cache_used); +#endif + /* this calls the protocol-specific function pointer previously set */ if(conn->curl_done) result = conn->curl_done(conn); @@ -2341,13 +2889,15 @@ CURLcode Curl_do(struct connectdata **connp) struct connectdata *conn = *connp; struct SessionHandle *data=conn->data; + conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to use */ + if(conn->curl_do) { /* generic protocol-specific function pointer set in curl_connect() */ result = conn->curl_do(conn); /* This was formerly done in transfer.c, but we better do it here */ - if((CURLE_WRITE_ERROR == result) && conn->bits.reuse) { + if((CURLE_SEND_ERROR == result) && conn->bits.reuse) { /* This was a re-use of a connection and we got a write error in the * DO-phase. Then we DISCONNECT this connection and have another attempt * to CONNECT and then DO again! The retry cannot possibly find another @@ -2370,6 +2920,16 @@ CURLcode Curl_do(struct connectdata **connp) return result; } +CURLcode Curl_do_more(struct connectdata *conn) +{ + CURLcode result=CURLE_OK; + + if(conn->curl_do_more) + result = conn->curl_do_more(conn); + + return result; +} + /* * local variables: * eval: (load-file "../curl-mode.el") diff --git a/Source/CTest/Curl/url.h b/Source/CTest/Curl/url.h index de3c02e..2da8ade 100644 --- a/Source/CTest/Curl/url.h +++ b/Source/CTest/Curl/url.h @@ -1,27 +1,27 @@ #ifndef __URL_H #define __URL_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* * Prototypes for library-wide functions provided by url.c @@ -32,7 +32,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...); CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */ CURLcode Curl_connect(struct SessionHandle *, struct connectdata **); CURLcode Curl_do(struct connectdata **); +CURLcode Curl_do_more(struct connectdata *); CURLcode Curl_done(struct connectdata *); CURLcode Curl_disconnect(struct connectdata *); - +CURLcode Curl_protocol_connect(struct connectdata *conn, + struct Curl_dns_entry *dns); #endif diff --git a/Source/CTest/Curl/urldata.h b/Source/CTest/Curl/urldata.h index de318f1..c4cab1a 100644 --- a/Source/CTest/Curl/urldata.h +++ b/Source/CTest/Curl/urldata.h @@ -1,33 +1,31 @@ #ifndef __URLDATA_H #define __URLDATA_H -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ /* This file is for lib internal stuff */ #include "setup.h" -#include "hostip.h" -#include "hash.h" #define PORT_FTP 21 #define PORT_TELNET 23 @@ -81,9 +79,15 @@ #include <curl/curl.h> #include "http_chunks.h" /* for the structs and enum stuff */ +#include "hostip.h" +#include "hash.h" + +#ifdef HAVE_ZLIB_H +#include <zlib.h> /* for content-encoding 08/28/02 jhrg */ +#endif /* Download buffer size, keep it fairly big for speed reasons */ -#define BUFSIZE (1024*20) +#define BUFSIZE CURL_MAX_WRITE_SIZE /* Initial size of the buffer to store headers in, it'll be enlarged in case of need. */ @@ -136,14 +140,15 @@ struct ssl_config_data { long version; /* what version the client wants to use */ long certverifyresult; /* result from the certificate verification */ long verifypeer; /* set TRUE if this is desired */ - long verifyhost; /* 0: no verif, 1: check that CN exists, 2: CN must match hostname */ + long verifyhost; /* 0: no verify + 1: check that CN exists + 2: CN must match hostname */ char *CApath; /* DOES NOT WORK ON WINDOWS */ char *CAfile; /* cerficate to verify peer against */ char *random_file; /* path to file containing "random" data */ char *egdsocket; /* path to file containing the EGD daemon socket */ char *cipher_list; /* list of ciphers to use */ - - long numsessions; /* SSL session id cache size */ + long numsessions; /* SSL session id cache size */ }; /**************************************************************************** @@ -179,7 +184,13 @@ struct FTP { char *entrypath; /* the PWD reply when we logged on */ char *cache; /* data cache between getresponse()-calls */ - size_t cache_size; /* size of cache in bytes */ + size_t cache_size; /* size of cache in bytes */ + bool dont_check; /* Set to TRUE to prevent the final (post-transfer) + file size and 226/250 status check. It should still + read the line, just ignore the result. */ + bool no_transfer; /* nothing was transfered, (possibly because a resumed + transfer already was complete) */ + }; /**************************************************************************** @@ -199,12 +210,18 @@ struct ConnectBits { bool httpproxy; /* if set, this transfer is done through a http proxy */ bool user_passwd; /* do we use user+password for this connection? */ bool proxy_user_passwd; /* user+password for the proxy? */ - + bool ipv6_ip; /* we communicate with a remove site specified with pure IPv6 + IP address */ bool use_range; bool rangestringalloc; /* the range string is malloc()'ed */ - bool resume_done; /* nothing was transfered, resumed transfer already - complete */ + bool do_more; /* this is set TRUE if the ->curl_do_more() function is + supposed to be called, after ->curl_do() */ + + bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding + on upload */ + + bool getheader; /* TRUE if header parsing is wanted */ }; /* @@ -220,6 +237,13 @@ struct Curl_transfer_keeper { struct timeval start; /* transfer started at this time */ struct timeval now; /* current time */ bool header; /* incoming data has HTTP header */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest is + normal data */ + HEADER_ALLBAD /* all was believed to be header */ + } badheader; /* the header was deemed bad and will be + written as body */ int headerline; /* counts header lines to better track the first one */ char *hbufp; /* points at *end* of header line */ @@ -236,19 +260,32 @@ struct Curl_transfer_keeper { bool write_after_100_header; /* should we enable the write after we received a 100-continue/timeout or directly */ + int content_encoding; /* What content encoding. sec 3.5, RFC2616. */ + +#define IDENTITY 0 /* No encoding */ +#define DEFLATE 1 /* zlib delfate [RFC 1950 & 1951] */ +#define GZIP 2 /* gzip algorithm [RFC 1952] */ +#define COMPRESS 3 /* Not handled, added for completeness */ + +#ifdef HAVE_LIBZ + bool zlib_init; /* True if zlib already initialized; + undefined if Content-Encdoing header. */ + z_stream z; /* State structure for zlib. */ +#endif /* for the low speed checks: */ time_t timeofdoc; long bodywrites; int writetype; - /* the highest fd we use + 1 */ - struct SessionHandle *data; - struct connectdata *conn; char *buf; char *uploadbuf; int maxfd; + /* pointers to the actual descriptors we check */ + fd_set *readfdp; + fd_set *writefdp; + /* the file descriptors to play with */ fd_set readfd; fd_set writefd; @@ -256,6 +293,8 @@ struct Curl_transfer_keeper { fd_set wkeepfd; int keepon; + bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload + and we're uploading the last chunk */ }; @@ -282,11 +321,11 @@ struct connectdata { #define PROT_FTPS (1<<9) #define PROT_SSL (1<<10) /* protocol requires SSL */ - Curl_addrinfo *hostaddr; /* IP-protocol independent host info pointer list */ - char *hostent_buf; /* pointer to allocated memory for name info */ + /* the particular host we use, in two different ways */ + struct Curl_dns_entry *connect_addr; #ifdef ENABLE_IPV6 - struct addrinfo *serv_addr; /* the particular host we use */ + struct addrinfo *serv_addr; #else struct sockaddr_in serv_addr; #endif @@ -324,6 +363,12 @@ struct connectdata { CURLcode (*curl_do)(struct connectdata *connect); CURLcode (*curl_done)(struct connectdata *connect); + /* If the curl_do() function is better made in two halves, this + * curl_do_more() function will be called afterwards, if set. For example + * for doing the FTP stuff after the PASV/PORT command. + */ + CURLcode (*curl_do_more)(struct connectdata *connect); + /* This function *MAY* be set to a protocol-dependent function that is run * after the connect() and everything is done, as a step in the connection. */ @@ -344,7 +389,6 @@ struct connectdata { /* READ stuff */ int sockfd; /* socket to read from or -1 */ int size; /* -1 if unknown at this point */ - bool getheader; /* TRUE if header parsing is wanted */ long *bytecountp; /* return number of bytes read or NULL */ /* WRITE stuff */ @@ -357,6 +401,7 @@ struct connectdata { struct dynamically_allocated_data { char *proxyuserpwd; /* free later if not NULL! */ char *uagent; /* free later if not NULL! */ + char *accept_encoding; /* free later if not NULL! 08/28/02 jhrg */ char *userpwd; /* free later if not NULL! */ char *rangeline; /* free later if not NULL! */ char *ref; /* free later if not NULL! */ @@ -410,9 +455,11 @@ struct connectdata { buffer, so the next read should read from where this pointer points to, and the 'upload_present' contains the number of bytes available at this position */ - char *upload_fromhere; + char *upload_fromhere; }; +/* The end of connectdata. 08/27/02 jhrg */ + /* * Struct to keep statistical and informational data. */ @@ -451,6 +498,7 @@ struct Progress { double t_connect; double t_pretransfer; double t_starttransfer; + double t_redirect; struct timeval start; struct timeval t_startsingle; @@ -483,6 +531,12 @@ typedef enum { #define MAX_CURL_PASSWORD_LENGTH 256 struct UrlState { + enum { + Curl_if_none, + Curl_if_easy, + Curl_if_multi + } used_interface; + /* buffers to store authentication data in, as parsed from input options */ char user[MAX_CURL_USER_LENGTH]; char passwd[MAX_CURL_PASSWORD_LENGTH]; @@ -542,6 +596,8 @@ struct DynamicStatic { bool proxy_alloc; /* http proxy string is malloc()'ed */ char *referer; /* referer string */ bool referer_alloc; /* referer sting is malloc()ed */ + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ }; /* @@ -553,7 +609,8 @@ struct DynamicStatic { */ struct UserDefined { - FILE *err; /* the stderr writes goes here */ + FILE *err; /* the stderr user data goes here */ + void *debugdata; /* the data that will be passed to fdebug */ char *errorbuffer; /* store failure messages in here */ char *proxyuserpwd; /* Proxy <user:password>, if used */ long proxyport; /* If non-zero, use this port number by default. If the @@ -574,6 +631,7 @@ struct UserDefined { bool free_referer; /* set TRUE if 'referer' points to a string we allocated */ char *useragent; /* User-Agent string */ + char *encoding; /* Accept-Encoding string 08/28/02 jhrg */ char *postfields; /* if POST, set the fields' values here */ size_t postfieldsize; /* if POST, this might have a size to use instead of strlen(), and then the data *may* be binary (contain @@ -584,6 +642,7 @@ struct UserDefined { curl_write_callback fwrite_header; /* function that stores headers */ curl_read_callback fread; /* function that reads the input */ curl_progress_callback fprogress; /* function for progress information */ + curl_debug_callback fdebug; /* function that write informational data */ void *progress_client; /* pointer to pass to the progress callback */ curl_passwd_callback fpasswd; /* call for password */ void *passwd_client; /* pass to the passwd callback */ @@ -603,6 +662,7 @@ struct UserDefined { char *key_passwd; /* plain text private key password */ char *crypto_engine; /* name of the crypto engine to use */ char *cookiejar; /* dump all cookies to this file */ + bool cookiesession; /* new cookie session? */ bool crlf; /* convert crlf on ftp upload(?) */ struct curl_slist *quote; /* after connection is established */ struct curl_slist *postquote; /* after the transfer */ @@ -622,7 +682,10 @@ struct UserDefined { char *krb4_level; /* what security level */ struct ssl_config_data ssl; /* user defined SSL stuff */ + curl_proxytype proxytype; /* what kind of proxy that is in use */ + int dns_cache_timeout; /* DNS cache timeout */ + long buffer_size; /* size of receive buffer to use */ /* Here follows boolean settings that define how to behave during this session. They are STATIC, set by libcurl users or at least initially @@ -645,13 +708,15 @@ struct UserDefined { bool no_body; bool set_port; bool upload; - bool use_netrc; + enum CURL_NETRC_OPTION + use_netrc; /* defined in include/curl.h */ bool verbose; bool krb4; /* kerberos4 connection requested */ bool reuse_forbid; /* forbidden to be reused, close after use */ bool reuse_fresh; /* do not re-use an existing connection */ bool expect100header; /* TRUE if we added Expect: 100-continue */ bool ftp_use_epsv; /* if EPSV is to be attempted or not */ + bool no_signal; /* do not use any signal/alarm handler */ bool global_dns_cache; }; @@ -668,7 +733,8 @@ struct UserDefined { * 'struct urlstate' instead. */ struct SessionHandle { - curl_hash *hostcache; + curl_hash *hostcache; + curl_share *share; /* Share, handles global variable mutexing */ struct UserDefined set; /* values set by the libcurl user */ struct DynamicStatic change; /* possibly modified userdefined data */ diff --git a/Source/CTest/Curl/version.c b/Source/CTest/Curl/version.c index ecaec67..41a71bf 100644 --- a/Source/CTest/Curl/version.c +++ b/Source/CTest/Curl/version.c @@ -1,25 +1,25 @@ -/***************************************************************************** +/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * In order to be useful for every potential user, curl and libcurl are - * dual-licensed under the MPL and the MIT/X-derivate licenses. + * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al. * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the MPL or the MIT/X-derivate - * licenses. You may pick one of these licenses. + * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id$ - *****************************************************************************/ + ***************************************************************************/ #include "setup.h" @@ -29,14 +29,9 @@ #include <curl/curl.h> #include "urldata.h" -char *curl_version(void) -{ - static char version[200]; - char *ptr; - strcpy(version, LIBCURL_NAME " " LIBCURL_VERSION ); - ptr=strchr(version, '\0'); - #ifdef USE_SSLEAY +static void getssl_version(char *ptr, long *num) +{ #if (SSLEAY_VERSION_NUMBER >= 0x905000) { @@ -44,6 +39,7 @@ char *curl_version(void) unsigned long ssleay_value; sub[1]='\0'; ssleay_value=SSLeay(); + *num = ssleay_value; if(ssleay_value < 0x906000) { ssleay_value=SSLEAY_VERSION_NUMBER; sub[0]='\0'; @@ -56,7 +52,7 @@ char *curl_version(void) sub[0]='\0'; } - sprintf(ptr, " (OpenSSL %lx.%lx.%lx%s)", + sprintf(ptr, " OpenSSL/%lx.%lx.%lx%s", (ssleay_value>>28)&0xf, (ssleay_value>>20)&0xff, (ssleay_value>>12)&0xff, @@ -64,8 +60,9 @@ char *curl_version(void) } #else + *num = SSLEAY_VERSION_NUMBER; #if (SSLEAY_VERSION_NUMBER >= 0x900000) - sprintf(ptr, " (SSL %lx.%lx.%lx)", + sprintf(ptr, " OpenSSL/%lx.%lx.%lx", (SSLEAY_VERSION_NUMBER>>28)&0xff, (SSLEAY_VERSION_NUMBER>>20)&0xff, (SSLEAY_VERSION_NUMBER>>12)&0xf); @@ -79,37 +76,128 @@ char *curl_version(void) else sub[0]='\0'; - sprintf(ptr, " (SSL %x.%x.%x%s)", + sprintf(ptr, " SSL/%x.%x.%x%s", (SSLEAY_VERSION_NUMBER>>12)&0xff, (SSLEAY_VERSION_NUMBER>>8)&0xf, (SSLEAY_VERSION_NUMBER>>4)&0xf, sub); } #endif #endif - ptr=strchr(ptr, '\0'); +} + +#endif + +char *curl_version(void) +{ + static char version[200]; + char *ptr; + long num; + strcpy(version, LIBCURL_NAME "/" LIBCURL_VERSION ); + ptr=strchr(version, '\0'); + +#ifdef USE_SSLEAY + getssl_version(ptr, &num); + ptr=strchr(version, '\0'); +#else + (void)num; /* no compiler warning please */ #endif -#if defined(KRB4) || defined(ENABLE_IPV6) - strcat(ptr, " ("); - ptr+=2; #ifdef KRB4 - sprintf(ptr, "krb4 "); + sprintf(ptr, " krb4"); ptr += strlen(ptr); #endif #ifdef ENABLE_IPV6 - sprintf(ptr, "ipv6 "); + sprintf(ptr, " ipv6"); ptr += strlen(ptr); #endif - sprintf(ptr, "enabled)"); +#ifdef HAVE_LIBZ + sprintf(ptr, " zlib/%s", zlibVersion()); ptr += strlen(ptr); #endif -#ifdef USE_ZLIB - sprintf(ptr, " (zlib %s)", zlibVersion()); - ptr += strlen(ptr); + return version; +} + +/* data for curl_version_info */ + +static const char *protocols[] = { +#ifndef CURL_DISABLE_FTP + "ftp", +#endif +#ifndef CURL_DISABLE_GOPHER + "gopher", +#endif +#ifndef CURL_DISABLE_TELNET + "telnet", +#endif +#ifndef CURL_DISABLE_DICT + "dict", +#endif +#ifndef CURL_DISABLE_LDAP + "ldap", +#endif +#ifndef CURL_DISABLE_HTTP + "http", +#endif +#ifndef CURL_DISABLE_FILE + "file", #endif - return version; +#ifdef USE_SSLEAY +#ifndef CURL_DISABLE_HTTP + "https", +#endif +#ifndef CURL_DISABLE_FTP + "ftps", +#endif +#endif + NULL +}; + +static curl_version_info_data version_info = { + CURLVERSION_FIRST, + LIBCURL_VERSION, + LIBCURL_VERSION_NUM, + OS, /* as found by configure or set by hand at build-time */ + 0 /* features is 0 by default */ +#ifdef ENABLE_IPV6 + | CURL_VERSION_IPV6 +#endif +#ifdef KRB4 + | CURL_VERSION_KERBEROS4 +#endif +#ifdef USE_SSLEAY + | CURL_VERSION_SSL +#endif +#ifdef HAVE_LIBZ + | CURL_VERSION_LIBZ +#endif + , + NULL, /* ssl_version */ + 0, /* ssl_version_num */ + NULL, /* zlib_version */ + protocols +}; + +curl_version_info_data *curl_version_info(CURLversion stamp) +{ +#ifdef USE_SSLEAY + static char ssl_buffer[80]; + long num; + getssl_version(ssl_buffer, &num); + + version_info.ssl_version = ssl_buffer; + version_info.ssl_version_num = num; + /* SSL stuff is left zero if undefined */ +#endif + +#ifdef HAVE_LIBZ + version_info.libz_version = zlibVersion(); + /* libz left NULL if non-existing */ +#endif + (void)stamp; /* avoid compiler warnings, we don't use this */ + + return &version_info; } /* |