ENH: Initial import

This commit is contained in:
Andy Cedilnik 2005-06-24 09:02:17 -04:00
parent c4036bd942
commit 7c730973bb
136 changed files with 42827 additions and 2 deletions

View File

@ -15,5 +15,5 @@ INCLUDE_DIRECTORIES(${LIBCURL_BINARY_DIR}/Testing)
FOREACH(TEST ${CURL_TESTS})
ADD_EXECUTABLE(${TEST} ${TEST}.c)
TARGET_LINK_LIBRARIES(${TEST} Curl)
ENDFOREACH(TEST)
TARGET_LINK_LIBRARIES(${TEST} cmcurl)
ENDFOREACH(TEST)

View File

@ -0,0 +1,34 @@
#ifdef CHECK_TYPE_SIZE_TYPE
@CHECK_TYPE_SIZE_PREINCLUDE@
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif /* HAVE_STDINT_H */
#ifdef HAVE_STDDEF_H
# include <stddef.h>
#endif /* HAVE_STDDEF_H */
@CHECK_TYPE_SIZE_PREMAIN@
#ifdef __CLASSIC_C__
int main(){
int ac;
char*av[];
#else
int main(int ac, char*av[]){
#endif
if(ac > 1000){return *av[0];}
return sizeof(CHECK_TYPE_SIZE_TYPE);
}
#else /* CHECK_TYPE_SIZE_TYPE */
# error "CHECK_TYPE_SIZE_TYPE has to specify the type"
#endif /* CHECK_TYPE_SIZE_TYPE */

View File

@ -0,0 +1,51 @@
#
# Check if the type exists and determine size of type. if the type
# exists, the size will be stored to the variable.
#
# CHECK_TYPE_SIZE - macro which checks the size of type
# VARIABLE - variable to store size if the type exists.
# HAVE_${VARIABLE} - does the variable exists or not
#
MACRO(CHECK_TYPE_SIZE TYPE VARIABLE)
SET(CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS 1)
IF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$")
SET(MACRO_CHECK_TYPE_SIZE_FLAGS
"-DCHECK_TYPE_SIZE_TYPE=\"${TYPE}\" ${CMAKE_REQUIRED_FLAGS}")
FOREACH(def HAVE_SYS_TYPES_H HAVE_STDINT_H HAVE_STDDEF_H)
IF("${def}")
SET(MACRO_CHECK_TYPE_SIZE_FLAGS
"${MACRO_CHECK_TYPE_SIZE_FLAGS} -D${def}")
ENDIF("${def}")
ENDFOREACH(def)
SET(CHECK_TYPE_SIZE_PREMAIN)
FOREACH(def ${CMAKE_EXTRA_INCLUDE_FILES})
SET(CHECK_TYPE_SIZE_PREMAIN "${CHECK_TYPE_SIZE_PREMAIN}#include \"${def}\"\n")
ENDFOREACH(def)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/CMake/CheckTypeSize.c.in"
"${CMAKE_BINARY_DIR}/CMakeTmp/CheckTypeSize.c" IMMEDIATE @ONLY)
FILE(READ "${CMAKE_BINARY_DIR}/CMakeTmp/CheckTypeSize.c"
CHECK_TYPE_SIZE_FILE_CONTENT)
MESSAGE(STATUS "Check size of ${TYPE}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_TYPE_SIZE_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ENDIF(CMAKE_REQUIRED_LIBRARIES)
TRY_RUN(${VARIABLE} HAVE_${VARIABLE}
${CMAKE_BINARY_DIR}
"${CMAKE_BINARY_DIR}/CMakeTmp/CheckTypeSize.c"
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_TYPE_SIZE_FLAGS}
"${CHECK_TYPE_SIZE_ADD_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
IF(HAVE_${VARIABLE})
MESSAGE(STATUS "Check size of ${TYPE} - done")
FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log
"Determining size of ${TYPE} passed with the following output:\n${OUTPUT}\n\n")
ELSE(HAVE_${VARIABLE})
MESSAGE(STATUS "Check size of ${TYPE} - failed")
FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeError.log
"Determining size of ${TYPE} failed with the following output:\n${OUTPUT}\nCheckTypeSize.c:\n${CHECK_TYPE_SIZE_FILE_CONTENT}\n\n")
ENDIF(HAVE_${VARIABLE})
ENDIF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$")
SET(CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS )
ENDMACRO(CHECK_TYPE_SIZE)

View File

@ -0,0 +1,535 @@
#ifdef TIME_WITH_SYS_TIME
/* Time with sys/time test */
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
int
main ()
{
if ((struct tm *) 0)
return 0;
;
return 0;
}
#endif
#ifdef HAVE_O_NONBLOCK
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int
main ()
{
/* try to compile O_NONBLOCK */
#if defined(sun) || defined(__sun__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# if defined(__SVR4) || defined(__srv4__)
# define PLATFORM_SOLARIS
# else
# define PLATFORM_SUNOS4
# endif
#endif
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX4)
# define PLATFORM_AIX_V3
#endif
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__)
#error "O_NONBLOCK does not work on this platform"
#endif
int socket;
int flags = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYADDR_R_5
#include <sys/types.h>
#include <netdb.h>
int
main ()
{
char * address;
int length;
int type;
struct hostent h;
struct hostent_data hdata;
int rc;
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
rc = gethostbyaddr_r(address, length, type, &h, &hdata);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYADDR_R_5_REENTRANT
#define _REENTRANT
#include <sys/types.h>
#include <netdb.h>
int
main ()
{
char * address;
int length;q
int type;
struct hostent h;
struct hostent_data hdata;
int rc;
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
rc = gethostbyaddr_r(address, length, type, &h, &hdata);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYADDR_R_7
#include <sys/types.h>
#include <netdb.h>
int
main ()
{
char * address;
int length;
int type;
struct hostent h;
char buffer[8192];
int h_errnop;
struct hostent * hp;
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
hp = gethostbyaddr_r(address, length, type, &h,
buffer, 8192, &h_errnop);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYADDR_R_7_REENTRANT
#define _REENTRANT
#include <sys/types.h>
#include <netdb.h>
int
main ()
{
char * address;
int length;
int type;
struct hostent h;
char buffer[8192];
int h_errnop;
struct hostent * hp;
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
hp = gethostbyaddr_r(address, length, type, &h,
buffer, 8192, &h_errnop);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYADDR_R_8
#include <sys/types.h>
#include <netdb.h>
int
main ()
{
char * address;
int length;
int type;
struct hostent h;
char buffer[8192];
int h_errnop;
struct hostent * hp;
int rc;
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
rc = gethostbyaddr_r(address, length, type, &h,
buffer, 8192, &hp, &h_errnop);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYADDR_R_8_REENTRANT
#define _REENTRANT
#include <sys/types.h>
#include <netdb.h>
int
main ()
{
char * address;
int length;
int type;
struct hostent h;
char buffer[8192];
int h_errnop;
struct hostent * hp;
int rc;
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
rc = gethostbyaddr_r(address, length, type, &h,
buffer, 8192, &hp, &h_errnop);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYNAME_R_3
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#undef NULL
#define NULL (void *)0
int
main ()
{
struct hostent_data data;
#ifndef gethostbyname_r
(void)gethostbyname_r;
#endif
gethostbyname_r(NULL, NULL, NULL);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYNAME_R_3_REENTRANT
#define _REENTRANT
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#undef NULL
#define NULL (void *)0
int
main ()
{
struct hostent_data data;
#ifndef gethostbyname_r
(void)gethostbyname_r;
#endif
gethostbyname_r(NULL, NULL, NULL);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYNAME_R_5
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#undef NULL
#define NULL (void *)0
int
main ()
{
#ifndef gethostbyname_r
(void)gethostbyname_r;
#endif
gethostbyname_r(NULL, NULL, NULL, 0, NULL);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYNAME_R_5_REENTRANT
#define _REENTRANT
#include <sys/types.h>
#include <netdb.h>
#undef NULL
#define NULL (void *)0
int
main ()
{
#ifndef gethostbyname_r
(void)gethostbyname_r;
#endif
gethostbyname_r(NULL, NULL, NULL, 0, NULL);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYNAME_R_6
#include <sys/types.h>
#include <netdb.h>
#undef NULL
#define NULL (void *)0
int
main ()
{
#ifndef gethostbyname_r
(void)gethostbyname_r;
#endif
gethostbyname_r(NULL, NULL, NULL, 0, NULL, NULL);
;
return 0;
}
#endif
#ifdef HAVE_GETHOSTBYNAME_R_6_REENTRANT
#define _REENTRANT
#include <sys/types.h>
#include <netdb.h>
#undef NULL
#define NULL (void *)0
int
main ()
{
#ifndef gethostbyname_r
(void)gethostbyname_r;
#endif
gethostbyname_r(NULL, NULL, NULL, 0, NULL, NULL);
;
return 0;
}
#endif
#ifdef HAVE_SOCKLEN_T
#include <sys/types.h>
#include <sys/socket.h>
int
main ()
{
if ((socklen_t *) 0)
return 0;
if (sizeof (socklen_t))
return 0;
;
return 0;
}
#endif
#ifdef HAVE_IN_ADDR_T
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int
main ()
{
if ((in_addr_t *) 0)
return 0;
if (sizeof (in_addr_t))
return 0;
;
return 0;
}
#endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
int main() { return 0; }
#endif
#ifdef RETSIGTYPE_TEST
#include <sys/types.h>
#include <signal.h>
#ifdef signal
# undef signal
#endif
#ifdef __cplusplus
extern "C" void (*signal (int, void (*)(int)))(int);
#else
void (*signal ()) ();
#endif
int
main ()
{
return 0;
}
#endif
#ifdef HAVE_INET_NTOA_R_DECL
#include <arpa/inet.h>
typedef void (*func_type)();
int main()
{
#ifndef inet_ntoa_r
func_type func;
func = (func_type)inet_ntoa_r;
#endif
return 0;
}
#endif
#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT
#define _REENTRANT
#include <arpa/inet.h>
typedef void (*func_type)();
int main()
{
#ifndef inet_ntoa_r
func_type func;
func = (func_type)&inet_ntoa_r;
#endif
return 0;
}
#endif
#ifdef HAVE_GETADDRINFO
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(void) {
struct addrinfo hints, *ai;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
#ifndef getaddrinfo
(void)getaddrinfo;
#endif
error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
if (error) {
return 1;
}
return 0;
}
#endif
#ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
#endif
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int main () { ; return 0; }
#endif
#ifdef HAVE_IOCTLSOCKET
#include <windows.h>
int
main ()
{
/* ioctlsocket source code */
int socket;
unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
;
return 0;
}
#endif
#ifdef HAVE_IOCTLSOCKET_CASE
#include <windows.h>
int
main ()
{
/* IoctlSocket source code */
int socket;
int flags = IoctlSocket(socket, FIONBIO, (long)1);
;
return 0;
}
#endif
#ifdef HAVE_FIONBIO
/* headers for FIONBIO test */
#include <unistd.h>
#include <stropts.h>
int
main ()
{
/* FIONBIO source test (old-style unix) */
int socket;
int flags = ioctl(socket, FIONBIO, &flags);
;
return 0;
}
#endif
#ifdef HAVE_SO_NONBLOCK
/* headers for SO_NONBLOCK test (BeOS) */
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
/* SO_NONBLOCK source code */
long b = 1;
int socket;
int flags = setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
return 0;
}
#endif
#ifdef HAVE_GLIBC_STRERROR_R
#include <string.h>
#include <errno.h>
int
main () {
char buffer[1024]; /* big enough to play with */
char *string =
strerror_r(EACCES, buffer, sizeof(buffer));
/* this should've returned a string */
if(!string || !string[0])
return 99;
return 0;
}
#endif
#ifdef HAVE_POSIX_STRERROR_R
#include <string.h>
#include <errno.h>
int
main () {
char buffer[1024]; /* big enough to play with */
int error =
strerror_r(EACCES, buffer, sizeof(buffer));
/* This should've returned zero, and written an error string in the
buffer.*/
if(!buffer[0] || error)
return 99;
return 0;
}
#endif
#ifdef HAVE_LONG_LONG_CONSTANT
int main()
{
long long c = 0x8000000000000000LL;
long long k = 0x7FFFFFFFFFFFFFFFLL;
if ( c == 0x8000000000000000LL && c != k )
{
return 0;
}
return 1;
}
#endif

View File

@ -0,0 +1,586 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.0)
PROJECT(LIBCURL C)
INCLUDE_REGULAR_EXPRESSION("^.*\\.h$")
# Setup package meta-data
SET(PACKAGE "curl")
SET(VERSION "7.12.1")
SET(PACKAGE_TARNAME "curl")
SET(PACKAGE_BUGREPORT " ")
SET(PACKAGE_NAME "curl")
SET(PACKAGE_VERSION "-")
SET(PACKAGE_STRING "curl-")
SET(PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/")
SET(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
# We need ansi c-flags, especially on HP
SET(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
SET(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
# If we are on AIX, do the _ALL_SOURCE magic
IF(${CMAKE_SYSTEM_NAME} MATCHES AIX)
SET(_ALL_SOURCE 1)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES AIX)
# Include all the necessary files for macros
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
INCLUDE (CheckFunctionExists)
INCLUDE (CheckIncludeFile)
INCLUDE (CheckIncludeFiles)
INCLUDE (CheckLibraryExists)
INCLUDE (CheckSymbolExists)
INCLUDE (CheckTypeSize)
SET(libCurl_SRCS
base64.c
connect.c
content_encoding.c
cookie.c
dict.c
easy.c
escape.c
file.c
formdata.c
ftp.c
getdate.c
getenv.c
getinfo.c
hash.c
hostares.c
hostasyn.c
hostip.c
hostip4.c
hostip6.c
hostsyn.c
hostthre.c
http.c
http_chunks.c
http_digest.c
http_negotiate.c
http_ntlm.c
if2ip.c
inet_ntop.c
inet_pton.c
krb4.c
llist.c
md5.c
memdebug.c
mprintf.c
multi.c
netrc.c
progress.c
sendf.c
share.c
speedcheck.c
ssluse.c
strequal.c
strerror.c
telnet.c
timeval.c
transfer.c
url.c
version.c
)
SET(CURL_DISABLE_LDAP 1)
IF(NOT CURL_DISABLE_LDAP)
SET(libCurl_SRCS
${libCurl_SRCS}
ldap.c
)
ENDIF(NOT CURL_DISABLE_LDAP)
# if we have Kerberos 4, right now this is never on
#OPTION(CURL_KRB4 "Use Kerberos 4" OFF)
IF(CURL_KRB4)
SET(libCurl_SRCS ${libCurl_SRCS}
krb4.c
security.c
)
ENDIF(CURL_KRB4)
#OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
MARK_AS_ADVANCED(CURL_MALLOC_DEBUG)
IF(CURL_MALLOC_DEBUG)
SET(libCurl_SRCS ${libCurl_SRCS}
memdebug.c
)
ENDIF(CURL_MALLOC_DEBUG)
# On windows preload settings
IF(WIN32)
INCLUDE(${LIBCURL_SOURCE_DIR}/Platforms/WindowsCache.cmake)
ENDIF(WIN32)
# This macro checks if the symbol exists in the library and if it
# does, it appends library to the list.
SET(CURL_LIBS "")
MACRO(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE)
CHECK_LIBRARY_EXISTS("${LIBRARY};${CURL_LIBS}" ${SYMBOL} ""
${VARIABLE})
IF(${VARIABLE})
SET(CURL_LIBS ${CURL_LIBS} ${LIBRARY})
ENDIF(${VARIABLE})
ENDMACRO(CHECK_LIBRARY_EXISTS_CONCAT)
# Check for all needed libraries
CHECK_LIBRARY_EXISTS_CONCAT("dl" dlopen HAVE_LIBDL)
CHECK_LIBRARY_EXISTS_CONCAT("ucb" gethostname HAVE_LIBUCB)
CHECK_LIBRARY_EXISTS_CONCAT("socket" connect HAVE_LIBSOCKET)
CHECK_LIBRARY_EXISTS("c" gethostbyname "" NOT_NEED_LIBNSL)
IF(NOT NOT_NEED_LIBNSL)
CHECK_LIBRARY_EXISTS_CONCAT("nsl" gethostbyname HAVE_LIBNSL)
ENDIF(NOT NOT_NEED_LIBNSL)
CHECK_LIBRARY_EXISTS_CONCAT("ws2_32" getch HAVE_LIBWS2_32)
CHECK_LIBRARY_EXISTS_CONCAT("winmm" getch HAVE_LIBWINMM)
IF(NOT CURL_SPECIAL_LIBZ)
CHECK_LIBRARY_EXISTS_CONCAT("z" inflateEnd HAVE_LIBZ)
ENDIF(NOT CURL_SPECIAL_LIBZ)
#OPTION(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" OFF)
MARK_AS_ADVANCED(CMAKE_USE_OPENSSL)
IF(CMAKE_USE_OPENSSL)
CHECK_LIBRARY_EXISTS_CONCAT("crypto" CRYPTO_lock HAVE_LIBCRYPTO)
CHECK_LIBRARY_EXISTS_CONCAT("ssl" SSL_connect HAVE_LIBSSL)
ENDIF(CMAKE_USE_OPENSSL)
# Check for symbol dlopen (same as HAVE_LIBDL)
CHECK_LIBRARY_EXISTS("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
# For other tests to use the same libraries
SET(CMAKE_REQUIRED_LIBRARIES ${CURL_LIBS})
IF(CURL_SPECIAL_LIBZ)
SET(CURL_LIBS ${CURL_LIBS} "${CURL_SPECIAL_LIBZ}")
INCLUDE_DIRECTORIES(${CURL_SPECIAL_LIBZ_INCLUDES})
SET(HAVE_LIBZ 0)
SET(HAVE_ZLIB_H 0)
ENDIF(CURL_SPECIAL_LIBZ)
# If we have features.h, then do the _BSD_SOURCE magic
CHECK_INCLUDE_FILE("features.h" HAVE_FEATURES_H)
IF(HAVE_FEATURES_H)
SET_SOURCE_FILES_PROPERTIES(
cookie.c
easy.c
formdata.c
getenv.c
hash.c
http.c
if2ip.c
mprintf.c
multi.c
sendf.c
telnet.c
transfer.c
url.c
COMPILE_FLAGS -D_BSD_SOURCE)
ENDIF(HAVE_FEATURES_H)
# Check if header file exists and add it to the list.
MACRO(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
CHECK_INCLUDE_FILES("${CURL_INCLUDES};${FILE}" ${VARIABLE})
IF(${VARIABLE})
SET(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
ENDIF(${VARIABLE})
ENDMACRO(CHECK_INCLUDE_FILE_CONCAT)
# Check for header files
CHECK_INCLUDE_FILE_CONCAT("stdio.h" HAVE_STDIO_H)
CHECK_INCLUDE_FILE_CONCAT("stddef.h" HAVE_STDDEF_H)
CHECK_INCLUDE_FILE_CONCAT("sys/types.h" HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILE_CONCAT("inttypes.h" HAVE_INTTYPES_H)
CHECK_INCLUDE_FILE_CONCAT("alloca.h" HAVE_ALLOCA_H)
CHECK_INCLUDE_FILE_CONCAT("arpa/inet.h" HAVE_ARPA_INET_H)
CHECK_INCLUDE_FILE_CONCAT("dlfcn.h" HAVE_DLFCN_H)
CHECK_INCLUDE_FILE_CONCAT("fcntl.h" HAVE_FCNTL_H)
CHECK_INCLUDE_FILE_CONCAT("malloc.h" HAVE_MALLOC_H)
CHECK_INCLUDE_FILE_CONCAT("memory.h" HAVE_MEMORY_H)
CHECK_INCLUDE_FILE_CONCAT("netdb.h" HAVE_NETDB_H)
CHECK_INCLUDE_FILE_CONCAT("sys/poll.h" HAVE_SYS_POLL_H)
CHECK_INCLUDE_FILE_CONCAT("assert.h" HAVE_ASSERT_H)
CHECK_INCLUDE_FILE_CONCAT("limits.h" HAVE_LIMITS_H)
IF(CMAKE_USE_OPENSSL)
CHECK_INCLUDE_FILE_CONCAT("openssl/x509.h" HAVE_OPENSSL_X509_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/engine.h" HAVE_OPENSSL_ENGINE_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/rsa.h" HAVE_OPENSSL_RSA_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/pem.h" HAVE_OPENSSL_PEM_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/ssl.h" HAVE_OPENSSL_SSL_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/err.h" HAVE_OPENSSL_ERR_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/rand.h" HAVE_OPENSSL_RAND_H)
ENDIF(CMAKE_USE_OPENSSL)
IF(NOT CURL_SPECIAL_LIBZ)
CHECK_INCLUDE_FILE_CONCAT("zlib.h" HAVE_ZLIB_H)
ENDIF(NOT CURL_SPECIAL_LIBZ)
CHECK_INCLUDE_FILE_CONCAT("sys/socket.h" HAVE_SYS_SOCKET_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/in.h" HAVE_NETINET_IN_H)
CHECK_INCLUDE_FILE_CONCAT("net/if.h" HAVE_NET_IF_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/if_ether.h"
HAVE_NETINET_IF_ETHER_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/tcp.h"
HAVE_NETINET_TCP_H)
CHECK_INCLUDE_FILE_CONCAT("sys/select.h" HAVE_SYS_SELECT_H)
CHECK_INCLUDE_FILE_CONCAT("utime.h" HAVE_UTIME_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/in.h" HAVE_NETINET_IN_H)
CHECK_INCLUDE_FILE_CONCAT("pwd.h" HAVE_PWD_H)
CHECK_INCLUDE_FILE_CONCAT("sgtty.h" HAVE_SGTTY_H)
CHECK_INCLUDE_FILE_CONCAT("stdint.h" HAVE_STDINT_H)
CHECK_INCLUDE_FILE_CONCAT("stdlib.h" HAVE_STDLIB_H)
CHECK_INCLUDE_FILE_CONCAT("string.h" HAVE_STRING_H)
CHECK_INCLUDE_FILE_CONCAT("strings.h" HAVE_STRINGS_H)
CHECK_INCLUDE_FILE_CONCAT("sys/param.h" HAVE_SYS_PARAM_H)
CHECK_INCLUDE_FILE_CONCAT("sys/stat.h" HAVE_SYS_STAT_H)
CHECK_INCLUDE_FILE_CONCAT("sys/time.h" HAVE_SYS_TIME_H)
CHECK_INCLUDE_FILE_CONCAT("termios.h" HAVE_TERMIOS_H)
CHECK_INCLUDE_FILE_CONCAT("termio.h" HAVE_TERMIO_H)
CHECK_INCLUDE_FILE_CONCAT("io.h" HAVE_IO_H)
CHECK_INCLUDE_FILE_CONCAT("time.h" HAVE_TIME_H)
CHECK_INCLUDE_FILE_CONCAT("unistd.h" HAVE_UNISTD_H)
CHECK_INCLUDE_FILE_CONCAT("sys/utime.h" HAVE_SYS_UTIME_H)
CHECK_INCLUDE_FILE_CONCAT("winsock.h" HAVE_WINSOCK_H)
CHECK_INCLUDE_FILE_CONCAT("sockio.h" HAVE_SOCKIO_H)
CHECK_INCLUDE_FILE_CONCAT("sys/sockio.h" HAVE_SYS_SOCKIO_H)
CHECK_INCLUDE_FILE_CONCAT("x509.h" HAVE_X509_H)
CHECK_INCLUDE_FILE_CONCAT("setjmp.h" HAVE_SETJMP_H)
CHECK_INCLUDE_FILE_CONCAT("signal.h" HAVE_SIGNAL_H)
CHECK_INCLUDE_FILE_CONCAT("sys/ioctl.h" HAVE_SYS_IOCTL_H)
CHECK_INCLUDE_FILE_CONCAT("sys/utsname.h" HAVE_SYS_UTSNAME_H)
CHECK_TYPE_SIZE(size_t SIZEOF_SIZE_T)
CHECK_TYPE_SIZE(ssize_t SIZEOF_SSIZE_T)
CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
CHECK_TYPE_SIZE("long double" SIZEOF_LONG_DOUBLE)
IF(NOT HAVE_SIZEOF_SSIZE_T)
SET(ssize_t int)
ENDIF(NOT HAVE_SIZEOF_SSIZE_T)
IF(HAVE_SIZEOF_LONG_LONG)
SET(HAVE_LONGLONG 1)
ENDIF(HAVE_SIZEOF_LONG_LONG)
FIND_FILE(RANDOM_FILE urandom /dev)
MARK_AS_ADVANCED(RANDOM_FILE)
# Check for some functions that are used
CHECK_SYMBOL_EXISTS(socket "${CURL_INCLUDES}" HAVE_SOCKET)
CHECK_SYMBOL_EXISTS(poll "${CURL_INCLUDES}" HAVE_POLL)
CHECK_SYMBOL_EXISTS(select "${CURL_INCLUDES}" HAVE_SELECT)
CHECK_SYMBOL_EXISTS(strdup "${CURL_INCLUDES}" HAVE_STRDUP)
CHECK_SYMBOL_EXISTS(strstr "${CURL_INCLUDES}" HAVE_STRSTR)
CHECK_SYMBOL_EXISTS(strtok_r "${CURL_INCLUDES}" HAVE_STRTOK_R)
CHECK_SYMBOL_EXISTS(strftime "${CURL_INCLUDES}" HAVE_STRFTIME)
CHECK_SYMBOL_EXISTS(uname "${CURL_INCLUDES}" HAVE_UNAME)
CHECK_SYMBOL_EXISTS(strcasecmp "${CURL_INCLUDES}" HAVE_STRCASECMP)
CHECK_SYMBOL_EXISTS(stricmp "${CURL_INCLUDES}" HAVE_STRICMP)
CHECK_SYMBOL_EXISTS(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI)
CHECK_SYMBOL_EXISTS(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI)
IF(NOT HAVE_STRNCMPI)
SET(HAVE_STRCMPI)
ENDIF(NOT HAVE_STRNCMPI)
CHECK_SYMBOL_EXISTS(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
CHECK_SYMBOL_EXISTS(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
CHECK_SYMBOL_EXISTS(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR)
CHECK_SYMBOL_EXISTS(inet_pton "${CURL_INCLUDES}" HAVE_INET_PTON)
CHECK_SYMBOL_EXISTS(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA)
CHECK_SYMBOL_EXISTS(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
CHECK_SYMBOL_EXISTS(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR)
CHECK_SYMBOL_EXISTS(tcgetattr "${CURL_INCLUDES}" HAVE_TCGETATTR)
CHECK_SYMBOL_EXISTS(perror "${CURL_INCLUDES}" HAVE_PERROR)
CHECK_SYMBOL_EXISTS(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
CHECK_SYMBOL_EXISTS(setvbuf "${CURL_INCLUDES}" HAVE_SETVBUF)
CHECK_SYMBOL_EXISTS(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
CHECK_SYMBOL_EXISTS(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
CHECK_SYMBOL_EXISTS(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT)
CHECK_SYMBOL_EXISTS(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
CHECK_SYMBOL_EXISTS(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
CHECK_SYMBOL_EXISTS(utime "${CURL_INCLUDES}" HAVE_UTIME)
IF(CMAKE_USE_OPENSSL)
CHECK_SYMBOL_EXISTS(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
CHECK_SYMBOL_EXISTS(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
CHECK_SYMBOL_EXISTS(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
CHECK_SYMBOL_EXISTS(CRYPTO_cleanup_all_ex_data "${CURL_INCLUDES}"
HAVE_CRYPTO_CLEANUP_ALL_EX_DATA)
ENDIF(CMAKE_USE_OPENSSL)
CHECK_SYMBOL_EXISTS(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
CHECK_SYMBOL_EXISTS(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
CHECK_SYMBOL_EXISTS(gethostbyname "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME)
CHECK_SYMBOL_EXISTS(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
CHECK_SYMBOL_EXISTS(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
CHECK_SYMBOL_EXISTS(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
CHECK_SYMBOL_EXISTS(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
IF(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
SET(HAVE_SIGNAL 1)
ENDIF(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
CHECK_SYMBOL_EXISTS(uname "${CURL_INCLUDES}" HAVE_UNAME)
CHECK_SYMBOL_EXISTS(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
CHECK_SYMBOL_EXISTS(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64)
CHECK_SYMBOL_EXISTS(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R)
CHECK_SYMBOL_EXISTS(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
CHECK_SYMBOL_EXISTS(perror "${CURL_INCLUDES}" HAVE_PERROR)
# only build compat strtok if we need to
IF (NOT HAVE_STRTOK_R)
SET(libCurl_SRCS ${libCurl_SRCS}
strtok.c
)
ENDIF (NOT HAVE_STRTOK_R)
IF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
SET(libCurl_SRCS ${libCurl_SRCS}
strtoofft.c
)
ENDIF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
# sigaction and sigsetjmp are special. Use special mechanism for
# detecting those, but only if previous attempt failed.
IF(HAVE_SIGNAL_H)
CHECK_SYMBOL_EXISTS(sigaction "signal.h" HAVE_SIGACTION)
ENDIF(HAVE_SIGNAL_H)
IF(NOT HAVE_SIGSETJMP)
IF(HAVE_SETJMP_H)
CHECK_SYMBOL_EXISTS(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
IF(HAVE_MACRO_SIGSETJMP)
SET(HAVE_SIGSETJMP 1)
ENDIF(HAVE_MACRO_SIGSETJMP)
ENDIF(HAVE_SETJMP_H)
ENDIF(NOT HAVE_SIGSETJMP)
# For other curl specific tests, use this macro.
MACRO(CURL_INTERNAL_TEST CURL_TEST)
IF("${CURL_TEST}" MATCHES "^${CURL_TEST}$")
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CURL_TEST_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ENDIF(CMAKE_REQUIRED_LIBRARIES)
MESSAGE(STATUS "Performing Curl Test ${CURL_TEST}")
TRY_COMPILE(${CURL_TEST}
${CMAKE_BINARY_DIR}
${LIBCURL_SOURCE_DIR}/CMake/CurlTests.c
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CURL_TEST_ADD_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
IF(${CURL_TEST})
SET(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
MESSAGE(STATUS "Performing Curl Test ${CURL_TEST} - Success")
ELSE(${CURL_TEST})
MESSAGE(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
SET(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeError.log
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
"${OUTPUT}\n")
ENDIF(${CURL_TEST})
ENDIF("${CURL_TEST}" MATCHES "^${CURL_TEST}$")
ENDMACRO(CURL_INTERNAL_TEST)
MACRO(CURL_INTERNAL_TEST_RUN CURL_TEST)
IF("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$")
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CURL_TEST_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ENDIF(CMAKE_REQUIRED_LIBRARIES)
MESSAGE(STATUS "Performing Curl Test ${CURL_TEST}")
TRY_RUN(${CURL_TEST} ${CURL_TEST}_COMPILE
${CMAKE_BINARY_DIR}
${LIBCURL_SOURCE_DIR}/CMake/CurlTests.c
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CURL_TEST_ADD_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
IF(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
SET(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
MESSAGE(STATUS "Performing Curl Test ${CURL_TEST} - Success")
ELSE(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
MESSAGE(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
SET(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
FILE(APPEND "${CMAKE_BINARY_DIR}/CMakeError.log"
"Performing Curl Test ${CURL_TEST} failed with the following output:\n"
"${OUTPUT}")
IF(${CURL_TEST}_COMPILE)
FILE(APPEND "${CMAKE_BINARY_DIR}/CMakeError.log"
"There was a running problem of this test\n")
ENDIF(${CURL_TEST}_COMPILE)
FILE(APPEND "${CMAKE_BINARY_DIR}/CMakeError.log"
"\n\n")
ENDIF(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
ENDIF("${CURL_TEST}_COMPILE" MATCHES "^${CURL_TEST}_COMPILE$")
ENDMACRO(CURL_INTERNAL_TEST_RUN)
# Do curl specific tests
#OPTION(CURL_HAVE_DISABLED_NONBLOCKING "Disable non-blocking socket detection" OFF)
SET(CURL_NONBLOCKING_TESTS)
IF(NOT CURL_HAVE_DISABLED_NONBLOCKING)
SET(CURL_NONBLOCKING_TESTS
HAVE_FIONBIO
HAVE_IOCTLSOCKET
HAVE_IOCTLSOCKET_CASE
HAVE_O_NONBLOCK
HAVE_SO_NONBLOCK
)
ENDIF(NOT CURL_HAVE_DISABLED_NONBLOCKING)
FOREACH(CURL_TEST
${CURL_NONBLOCKING_TESTS}
TIME_WITH_SYS_TIME
HAVE_O_NONBLOCKHAVE_GETHOSTBYADDR_R_5
HAVE_GETHOSTBYADDR_R_7
HAVE_GETHOSTBYADDR_R_8
HAVE_GETHOSTBYADDR_R_5_REENTRANT
HAVE_GETHOSTBYADDR_R_7_REENTRANT
HAVE_GETHOSTBYADDR_R_8_REENTRANT
HAVE_GETHOSTBYNAME_R_3
HAVE_GETHOSTBYNAME_R_5
HAVE_GETHOSTBYNAME_R_6
HAVE_GETHOSTBYNAME_R_3_REENTRANT
HAVE_GETHOSTBYNAME_R_5_REENTRANT
HAVE_GETHOSTBYNAME_R_6_REENTRANT
HAVE_SOCKLEN_T
HAVE_IN_ADDR_T
STDC_HEADERS
RETSIGTYPE_TEST
HAVE_INET_NTOA_R_DECL
HAVE_INET_NTOA_R_DECL_REENTRANT
HAVE_GETADDRINFO
HAVE_FILE_OFFSET_BITS
)
CURL_INTERNAL_TEST(${CURL_TEST})
ENDFOREACH(CURL_TEST)
IF(HAVE_FILE_OFFSET_BITS)
SET(_FILE_OFFSET_BITS 64)
ENDIF(HAVE_FILE_OFFSET_BITS)
FOREACH(CURL_TEST
HAVE_GLIBC_STRERROR_R
HAVE_POSIX_STRERROR_R
HAVE_LONG_LONG_CONSTANT
)
CURL_INTERNAL_TEST_RUN(${CURL_TEST})
ENDFOREACH(CURL_TEST)
# Check for reentrant
FOREACH(CURL_TEST
HAVE_GETHOSTBYADDR_R_5
HAVE_GETHOSTBYADDR_R_7
HAVE_GETHOSTBYADDR_R_8
HAVE_GETHOSTBYNAME_R_3
HAVE_GETHOSTBYNAME_R_5
HAVE_GETHOSTBYNAME_R_6
HAVE_INET_NTOA_R_DECL_REENTRANT)
IF(NOT ${CURL_TEST})
IF(${CURL_TEST}_REENTRANT)
SET(NEED_REENTRANT 1)
ENDIF(${CURL_TEST}_REENTRANT)
ENDIF(NOT ${CURL_TEST})
ENDFOREACH(CURL_TEST)
IF(NEED_REENTRANT)
FOREACH(CURL_TEST
HAVE_GETHOSTBYADDR_R_5
HAVE_GETHOSTBYADDR_R_7
HAVE_GETHOSTBYADDR_R_8
HAVE_GETHOSTBYNAME_R_3
HAVE_GETHOSTBYNAME_R_5
HAVE_GETHOSTBYNAME_R_6)
SET(${CURL_TEST} 0)
IF(${CURL_TEST}_REENTRANT)
SET(${CURL_TEST} 1)
ENDIF(${CURL_TEST}_REENTRANT)
ENDFOREACH(CURL_TEST)
ENDIF(NEED_REENTRANT)
IF(HAVE_INET_NTOA_R_DECL_REENTRANT)
SET(HAVE_INET_NTOA_R_DECL 1)
SET(NEED_REENTRANT 1)
ENDIF(HAVE_INET_NTOA_R_DECL_REENTRANT)
# Some other minor tests
IF(NOT HAVE_SOCKLEN_T)
SET(socklen_t "int")
ENDIF(NOT HAVE_SOCKLEN_T)
IF(NOT HAVE_IN_ADDR_T)
SET(in_addr_t "unsigned long")
ENDIF(NOT HAVE_IN_ADDR_T)
# Fix libz / zlib.h
IF(NOT CURL_SPECIAL_LIBZ)
IF(NOT HAVE_LIBZ)
SET(HAVE_ZLIB_H 0)
ENDIF(NOT HAVE_LIBZ)
IF(NOT HAVE_ZLIB_H)
SET(HAVE_LIBZ 0)
ENDIF(NOT HAVE_ZLIB_H)
ENDIF(NOT CURL_SPECIAL_LIBZ)
IF(_FILE_OFFSET_BITS)
SET(_FILE_OFFSET_BITS 64)
ENDIF(_FILE_OFFSET_BITS)
SET(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
SET(CMAKE_EXTRA_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/curl/curl.h")
CHECK_TYPE_SIZE("curl_off_t" SIZEOF_CURL_OFF_T)
SET(CMAKE_EXTRA_INCLUDE_FILES)
SET(CMAKE_REQUIRED_FLAGS)
# Check for nonblocking
SET(HAVE_DISABLED_NONBLOCKING 1)
IF(HAVE_FIONBIO OR
HAVE_IOCTLSOCKET OR
HAVE_IOCTLSOCKET_CASE OR
HAVE_O_NONBLOCK)
SET(HAVE_DISABLED_NONBLOCKING)
ENDIF(HAVE_FIONBIO OR
HAVE_IOCTLSOCKET OR
HAVE_IOCTLSOCKET_CASE OR
HAVE_O_NONBLOCK)
IF(RETSIGTYPE_TEST)
SET(RETSIGTYPE void)
ELSE(RETSIGTYPE_TEST)
SET(RETSIGTYPE int)
ENDIF(RETSIGTYPE_TEST)
IF(CMAKE_COMPILER_IS_GNUCC AND APPLE)
# The Mac version of GCC warns about use of long double. Disable it.
GET_SOURCE_FILE_PROPERTY(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS)
IF(MPRINTF_COMPILE_FLAGS)
SET(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double")
ELSE(MPRINTF_COMPILE_FLAGS)
SET(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
ENDIF(MPRINTF_COMPILE_FLAGS)
SET_SOURCE_FILES_PROPERTIES(mprintf.c PROPERTIES
COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
ENDIF(CMAKE_COMPILER_IS_GNUCC AND APPLE)
# The rest of the build
INCLUDE_DIRECTORIES(${LIBCURL_SOURCE_DIR})
INCLUDE_DIRECTORIES(${LIBCURL_BINARY_DIR})
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
CONFIGURE_FILE(${LIBCURL_SOURCE_DIR}/config.h.in
${LIBCURL_BINARY_DIR}/config.h)
ADD_LIBRARY(cmcurl ${libCurl_SRCS})
TARGET_LINK_LIBRARIES(cmcurl ${CURL_LIBS})
OPTION(CURL_TESTING "Do libCurl testing" OFF)
IF(CURL_TESTING)
SUBDIRS(Testing)
ENDIF(CURL_TESTING)
ADD_EXECUTABLE(LIBCURL Testing/curltest.c)
TARGET_LINK_LIBRARIES(LIBCURL cmcurl)
ADD_TEST(curl "${EXECUTABLE_OUTPUT_PATH}/LIBCURL")

View File

@ -0,0 +1,123 @@
IF(NOT UNIX)
IF(WIN32)
SET(HAVE_LIBDL 0)
SET(HAVE_LIBUCB 0)
SET(HAVE_LIBSOCKET 0)
SET(NOT_NEED_LIBNSL 0)
SET(HAVE_LIBNSL 0)
SET(HAVE_LIBZ 0)
SET(HAVE_LIBCRYPTO 0)
SET(HAVE_DLOPEN 0)
SET(HAVE_ALLOCA_H 0)
SET(HAVE_ARPA_INET_H 0)
SET(HAVE_DLFCN_H 0)
SET(HAVE_FCNTL_H 1)
SET(HAVE_FEATURES_H 0)
SET(HAVE_INTTYPES_H 0)
SET(HAVE_IO_H 1)
SET(HAVE_MALLOC_H 1)
SET(HAVE_MEMORY_H 1)
SET(HAVE_NETDB_H 0)
SET(HAVE_NETINET_IF_ETHER_H 0)
SET(HAVE_NETINET_IN_H 0)
SET(HAVE_NET_IF_H 0)
SET(HAVE_PWD_H 0)
SET(HAVE_SETJMP_H 1)
SET(HAVE_SGTTY_H 0)
SET(HAVE_SIGNAL_H 1)
SET(HAVE_SOCKIO_H 0)
SET(HAVE_STDINT_H 0)
SET(HAVE_STDLIB_H 1)
SET(HAVE_STRINGS_H 0)
SET(HAVE_STRING_H 1)
SET(HAVE_SYS_PARAM_H 0)
SET(HAVE_SYS_POLL_H 0)
SET(HAVE_SYS_SELECT_H 0)
SET(HAVE_SYS_SOCKET_H 0)
SET(HAVE_SYS_SOCKIO_H 0)
SET(HAVE_SYS_STAT_H 1)
SET(HAVE_SYS_TIME_H 0)
SET(HAVE_SYS_TYPES_H 1)
SET(HAVE_SYS_UTIME_H 1)
SET(HAVE_TERMIOS_H 0)
SET(HAVE_TERMIO_H 0)
SET(HAVE_TIME_H 1)
SET(HAVE_UNISTD_H 0)
SET(HAVE_UTIME_H 0)
SET(HAVE_WINSOCK_H 1)
SET(HAVE_X509_H 0)
SET(HAVE_ZLIB_H 0)
SET(HAVE_SIZEOF_LONG_DOUBLE 1)
SET(HAVE_SIZEOF_SSIZE_T 0)
SET(SIZEOF_LONG_DOUBLE 8)
SET(HAVE_SOCKET 1)
SET(HAVE_POLL 0)
SET(HAVE_SELECT 1)
SET(HAVE_STRDUP 1)
SET(HAVE_STRSTR 1)
SET(HAVE_STRTOK_R 0)
SET(HAVE_STRFTIME 1)
SET(HAVE_UNAME 0)
SET(HAVE_STRCASECMP 0)
SET(HAVE_STRICMP 1)
SET(HAVE_STRCMPI 1)
SET(HAVE_GETHOSTBYADDR 1)
SET(HAVE_GETTIMEOFDAY 0)
SET(HAVE_INET_ADDR 1)
SET(HAVE_INET_NTOA 1)
SET(HAVE_INET_NTOA_R 0)
SET(HAVE_TCGETATTR 0)
SET(HAVE_TCSETATTR 0)
SET(HAVE_PERROR 1)
SET(HAVE_CLOSESOCKET 1)
SET(HAVE_SETVBUF 0)
SET(HAVE_SIGSETJMP 0)
SET(HAVE_GETPASS_R 0)
SET(HAVE_STRLCAT 0)
SET(HAVE_GETPWUID 0)
SET(HAVE_GETEUID 0)
SET(HAVE_UTIME 1)
SET(HAVE_RAND_EGD 0)
SET(HAVE_RAND_SCREEN 0)
SET(HAVE_RAND_STATUS 0)
SET(HAVE_GMTIME_R 0)
SET(HAVE_LOCALTIME_R 0)
SET(HAVE_GETHOSTBYADDR_R 0)
SET(HAVE_GETHOSTBYNAME_R 0)
SET(HAVE_SIGNAL_FUNC 1)
SET(HAVE_SIGNAL_MACRO 0)
SET(HAVE_GETHOSTBYADDR_R_5 0)
SET(HAVE_GETHOSTBYADDR_R_5_REENTRANT 0)
SET(HAVE_GETHOSTBYADDR_R_7 0)
SET(HAVE_GETHOSTBYADDR_R_7_REENTRANT 0)
SET(HAVE_GETHOSTBYADDR_R_8 0)
SET(HAVE_GETHOSTBYADDR_R_8_REENTRANT 0)
SET(HAVE_GETHOSTBYNAME_R_3 0)
SET(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
SET(HAVE_GETHOSTBYNAME_R_5 0)
SET(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0)
SET(HAVE_GETHOSTBYNAME_R_6 0)
SET(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
SET(TIME_WITH_SYS_TIME 0)
SET(HAVE_O_NONBLOCK 0)
SET(HAVE_IN_ADDR_T 0)
SET(HAVE_SOCKLEN_T 0)
SET(HAVE_INET_NTOA_R_DECL 0)
SET(HAVE_INET_NTOA_R_DECL_REENTRANT 0)
SET(HAVE_GETADDRINFO 0)
SET(STDC_HEADERS 1)
SET(RETSIGTYPE_TEST 1)
SET(HAVE_SIGACTION 0)
SET(HAVE_MACRO_SIGSETJMP 0)
ELSE(WIN32)
MESSAGE("This file should be included on Windows platform only")
ENDIF(WIN32)
ENDIF(NOT UNIX)

View File

@ -0,0 +1,486 @@
/* lib/config.h. Generated by configure. */
/* lib/config.h.in. Generated from configure.in by autoheader. */
/* Name of this package! */
#define PACKAGE "curl"
/* Version number of this archive. */
#define VERSION "7.10.2"
/* Define if you have the getpass function. */
/* #undef HAVE_GETPASS */
/* Define cpu-machine-OS */
#define OS "powerpc-ibm-aix5.1.0.0"
/* Define if you have the gethostbyaddr_r() function with 5 arguments */
#define HAVE_GETHOSTBYADDR_R_5 1
/* Define if you have the gethostbyaddr_r() function with 7 arguments */
/* #undef HAVE_GETHOSTBYADDR_R_7 */
/* Define if you have the gethostbyaddr_r() function with 8 arguments */
/* #undef HAVE_GETHOSTBYADDR_R_8 */
/* Define if you have the gethostbyname_r() function with 3 arguments */
#define HAVE_GETHOSTBYNAME_R_3 1
/* Define if you have the gethostbyname_r() function with 5 arguments */
/* #undef HAVE_GETHOSTBYNAME_R_5 */
/* Define if you have the gethostbyname_r() function with 6 arguments */
/* #undef HAVE_GETHOSTBYNAME_R_6 */
/* Define if you have the inet_ntoa_r function declared. */
/* #undef HAVE_INET_NTOA_R_DECL */
/* Define if you need the _REENTRANT define for some functions */
/* #undef NEED_REENTRANT */
/* Define if you have the Kerberos4 libraries (including -ldes) */
/* #undef KRB4 */
/* Define if you want to enable IPv6 support */
#define ENABLE_IPV6 1
/* Define this to 'int' if ssize_t is not an available typedefed type */
/* #undef ssize_t */
/* Define this to 'int' if socklen_t is not an available typedefed type */
/* #undef socklen_t */
/* Define this as a suitable file to read random data from */
/* #undef RANDOM_FILE */
/* Define this to your Entropy Gathering Daemon socket pathname */
/* #undef EGD_SOCKET */
/* Define if you have a working OpenSSL installation */
/* #undef OPENSSL_ENABLED */
/* Define the one correct non-blocking socket method below */
/* #undef HAVE_FIONBIO */
/* #undef HAVE_IOCTLSOCKET */
/* #undef HAVE_IOCTLSOCKET_CASE */
/* #undef HAVE_O_NONBLOCK */
#define HAVE_DISABLED_NONBLOCKING 1
/* Define this to 'int' if in_addr_t is not an available typedefed type */
/* #undef in_addr_t */
/* Define to disable DICT */
/* #undef CURL_DISABLE_DICT */
/* Define to disable FILE */
/* #undef CURL_DISABLE_FILE */
/* Define to disable FTP */
/* #undef CURL_DISABLE_FTP */
/* Define to disable GOPHER */
/* #undef CURL_DISABLE_GOPHER */
/* Define to disable HTTP */
/* #undef CURL_DISABLE_HTTP */
/* Define to disable LDAP */
/* #undef CURL_DISABLE_LDAP */
/* Define to disable TELNET */
/* #undef CURL_DISABLE_TELNET */
/* Define if you have zlib present */
#define HAVE_LIBZ 1
/* CA bundle full path name */
#define CURL_CA_BUNDLE "/usr/local/share/curl/curl-ca-bundle.crt"
/* to disable FILE */
/* #undef CURL_DISABLE_FILE */
/* to disable FTP */
/* #undef CURL_DISABLE_FTP */
/* to disable GOPHER */
/* #undef CURL_DISABLE_GOPHER */
/* to disable HTTP */
/* #undef CURL_DISABLE_HTTP */
/* to disable LDAP */
/* #undef CURL_DISABLE_LDAP */
/* to disable TELNET */
/* #undef CURL_DISABLE_TELNET */
/* Set to explicitly specify we don't want to use thread-safe functions */
/* #undef DISABLED_THREADSAFE */
/* your Entropy Gathering Daemon socket pathname */
/* #undef EGD_SOCKET */
/* Define if you want to enable IPv6 support */
#define ENABLE_IPV6 1
/* Define to 1 if you have the <alloca.h> header file. */
#define HAVE_ALLOCA_H 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the `closesocket' function. */
/* #undef HAVE_CLOSESOCKET */
/* Define to 1 if you have the <crypto.h> header file. */
/* #undef HAVE_CRYPTO_H */
/* Define to 1 if you have the <des.h> header file. */
/* #undef HAVE_DES_H */
/* to disable NON-BLOCKING connections */
#define HAVE_DISABLED_NONBLOCKING 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the `dlopen' function. */
#define HAVE_DLOPEN 1
/* Define to 1 if you have the <err.h> header file. */
/* #undef HAVE_ERR_H */
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if getaddrinfo exists and works */
#define HAVE_GETADDRINFO 1
/* Define to 1 if you have the `geteuid' function. */
#define HAVE_GETEUID 1
/* Define to 1 if you have the `gethostbyaddr' function. */
#define HAVE_GETHOSTBYADDR 1
/* Define to 1 if you have the `gethostbyaddr_r' function. */
#define HAVE_GETHOSTBYADDR_R 1
/* Define to 1 if you have the `gethostbyname_r' function. */
#define HAVE_GETHOSTBYNAME_R 1
/* Define to 1 if you have the `getpass_r' function. */
/* #undef HAVE_GETPASS_R */
/* Define to 1 if you have the `getpwuid' function. */
#define HAVE_GETPWUID 1
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the `gmtime_r' function. */
#define HAVE_GMTIME_R 1
/* Define to 1 if you have the `inet_addr' function. */
#define HAVE_INET_ADDR 1
/* Define to 1 if you have the `inet_ntoa' function. */
#define HAVE_INET_NTOA 1
/* Define to 1 if you have the `inet_ntoa_r' function. */
#define HAVE_INET_NTOA_R 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <io.h> header file. */
/* #undef HAVE_IO_H */
/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
/* Define to 1 if you have the <krb.h> header file. */
/* #undef HAVE_KRB_H */
/* Define to 1 if you have the `crypto' library (-lcrypto). */
/* #undef HAVE_LIBCRYPTO */
/* Define to 1 if you have the `dl' library (-ldl). */
/* #undef HAVE_LIBDL */
/* Define to 1 if you have the `nsl' library (-lnsl). */
/* #undef HAVE_LIBNSL */
/* Define to 1 if you have the `resolv' library (-lresolv). */
/* #undef HAVE_LIBRESOLV */
/* Define to 1 if you have the `resolve' library (-lresolve). */
/* #undef HAVE_LIBRESOLVE */
/* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef HAVE_LIBSOCKET */
/* Define to 1 if you have the `ssl' library (-lssl). */
/* #undef HAVE_LIBSSL */
/* If zlib is available */
#define HAVE_LIBZ 1
/* Define to 1 if you have the `localtime_r' function. */
#define HAVE_LOCALTIME_R 1
/* Define to 1 if you have the <malloc.h> header file. */
#define HAVE_MALLOC_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <netdb.h> header file. */
#define HAVE_NETDB_H 1
/* Define to 1 if you have the <netinet/if_ether.h> header file. */
#define HAVE_NETINET_IF_ETHER_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H 1
/* Define to 1 if you have the <openssl/crypto.h> header file. */
/* #undef HAVE_OPENSSL_CRYPTO_H */
/* Define to 1 if you have the <openssl/engine.h> header file. */
/* #undef HAVE_OPENSSL_ENGINE_H */
/* Define to 1 if you have the <openssl/err.h> header file. */
/* #undef HAVE_OPENSSL_ERR_H */
/* Define to 1 if you have the <openssl/pem.h> header file. */
/* #undef HAVE_OPENSSL_PEM_H */
/* Define to 1 if you have the <openssl/rsa.h> header file. */
/* #undef HAVE_OPENSSL_RSA_H */
/* Define to 1 if you have the <openssl/ssl.h> header file. */
/* #undef HAVE_OPENSSL_SSL_H */
/* Define to 1 if you have the <openssl/x509.h> header file. */
/* #undef HAVE_OPENSSL_X509_H */
/* Define to 1 if you have the <pem.h> header file. */
/* #undef HAVE_PEM_H */
/* Define to 1 if you have the `perror' function. */
#define HAVE_PERROR 1
/* Define to 1 if you have the `poll' function. */
#define HAVE_POLL 1
/* Define to 1 if you have the <pwd.h> header file. */
#define HAVE_PWD_H 1
/* Define to 1 if you have the `RAND_egd' function. */
/* #undef HAVE_RAND_EGD */
/* Define to 1 if you have the `RAND_screen' function. */
/* #undef HAVE_RAND_SCREEN */
/* Define to 1 if you have the `RAND_status' function. */
/* #undef HAVE_RAND_STATUS */
/* Define to 1 if you have the <rsa.h> header file. */
/* #undef HAVE_RSA_H */
/* Define to 1 if you have the `select' function. */
#define HAVE_SELECT 1
/* Define to 1 if you have the <setjmp.h> header file. */
#define HAVE_SETJMP_H 1
/* Define to 1 if you have the `setvbuf' function. */
#define HAVE_SETVBUF 1
/* Define to 1 if you have the <sgtty.h> header file. */
#define HAVE_SGTTY_H 1
/* Define to 1 if you have the `sigaction' function. */
#define HAVE_SIGACTION 1
/* Define to 1 if you have the `signal' function. */
#define HAVE_SIGNAL 1
/* If you have sigsetjmp */
#define HAVE_SIGSETJMP 1
/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1
/* Define to 1 if you have the <ssl.h> header file. */
/* #undef HAVE_SSL_H */
/* Define to 1 if you have the <stdint.h> header file. */
/* #undef HAVE_STDINT_H */
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strcmpi' function. */
/* #undef HAVE_STRCMPI */
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `strftime' function. */
#define HAVE_STRFTIME 1
/* Define to 1 if you have the `stricmp' function. */
/* #undef HAVE_STRICMP */
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strlcat' function. */
/* #undef HAVE_STRLCAT */
/* Define to 1 if you have the `strlcpy' function. */
/* #undef HAVE_STRLCPY */
/* Define to 1 if you have the `strstr' function. */
#define HAVE_STRSTR 1
/* Define to 1 if you have the `strtok_r' function. */
#define HAVE_STRTOK_R 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/poll.h> header file. */
#define HAVE_SYS_POLL_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/sockio.h> header file. */
/* #undef HAVE_SYS_SOCKIO_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/utime.h> header file. */
/* #undef HAVE_SYS_UTIME_H */
/* Define to 1 if you have the `tcgetattr' function. */
#define HAVE_TCGETATTR 1
/* Define to 1 if you have the `tcsetattr' function. */
#define HAVE_TCSETATTR 1
/* Define to 1 if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1
/* Define to 1 if you have the <termio.h> header file. */
#define HAVE_TERMIO_H 1
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
/* Define to 1 if you have the `uname' function. */
#define HAVE_UNAME 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `utime' function. */
#define HAVE_UTIME 1
/* Define to 1 if you have the <utime.h> header file. */
#define HAVE_UTIME_H 1
/* Define to 1 if you have the <winsock.h> header file. */
/* #undef HAVE_WINSOCK_H */
/* Define to 1 if you have the <x509.h> header file. */
/* #undef HAVE_X509_H */
/* if you have the zlib.h header file */
/* #undef HAVE_ZLIB_H */
/* if you have the Kerberos4 libraries (including -ldes) */
/* #undef KRB4 */
/* cpu-machine-OS */
#define OS "powerpc-ibm-aix5.1.0.0"
/* Name of package */
#define PACKAGE "curl"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* a suitable file to read random data from */
/* #undef RANDOM_FILE */
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Version number of package */
#define VERSION "7.10.2"
/* Define to 1 if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define for large files, on AIX-style hosts. */
#define _LARGE_FILES 1
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* type to use in place of in_addr_t if not defined */
/* #undef in_addr_t */
/* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef size_t */
/* type to use in place of socklen_t if not defined */
/* #undef socklen_t */
/* Define to `int' if <sys/types.h> does not define. */
/* #undef ssize_t */

View File

@ -0,0 +1,19 @@
SET(CURL_TESTS
ftpget
ftpgetresp
ftpupload
getinmemory
persistant
sepheaders
simple
)
CONFIGURE_FILE(${LIBCURL_SOURCE_DIR}/Testing/testconfig.h.in
${LIBCURL_BINARY_DIR}/Testing/testconfig.h)
INCLUDE_DIRECTORIES(${LIBCURL_BINARY_DIR}/Testing)
FOREACH(TEST ${CURL_TESTS})
ADD_EXECUTABLE(${TEST} ${TEST}.c)
TARGET_LINK_LIBRARIES(${TEST} cmcurl)
ENDFOREACH(TEST)

View File

@ -0,0 +1,95 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
/* Copyright (c) 2000 David Odin (aka DindinX) for MandrakeSoft */
/* an attempt to use the curl library in concert with a gtk-threaded application */
#include <stdio.h>
#include <gtk/gtk.h>
#include <curl/curl.h>
#include <curl/types.h> /* new for v7 */
#include <curl/easy.h> /* new for v7 */
#include <pthread.h>
GtkWidget *Bar;
size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fread(ptr, size, nmemb, stream);
}
int my_progress_func(GtkWidget *Bar, int t, int d)
{
/* printf("%d / %d (%g %%)\n", d, t, d*100.0/t);*/
gdk_threads_enter();
gtk_progress_set_value(GTK_PROGRESS(Bar), d*100.0/t);
gdk_threads_leave();
return 0;
}
void *curl_thread(void *ptr)
{
CURL *curl;
CURLcode res;
FILE *outfile;
gchar *url = ptr;
curl = curl_easy_init();
if(curl)
{
outfile = fopen("/tmp/test.curl", "w");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FILE, outfile);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, Bar);
res = curl_easy_perform(curl);
fclose(outfile);
/* always cleanup */
curl_easy_cleanup(curl);
}
return NULL;
}
int main(int argc, char **argv)
{
GtkWidget *Window, *Frame, *Frame2;
GtkAdjustment *adj;
pthread_t curl_tid;
/* Init thread */
g_thread_init(NULL);
gtk_init(&argc, &argv);
Window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
Frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(Frame), GTK_SHADOW_OUT);
gtk_container_add(GTK_CONTAINER(Window), Frame);
Frame2 = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(Frame2), GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(Frame), Frame2);
gtk_container_set_border_width(GTK_CONTAINER(Frame2), 5);
adj = (GtkAdjustment*)gtk_adjustment_new(0, 0, 100, 0, 0, 0);
Bar = gtk_progress_bar_new_with_adjustment(adj);
gtk_container_add(GTK_CONTAINER(Frame2), Bar);
gtk_widget_show_all(Window);
pthread_create(&curl_tid, NULL, curl_thread, argv[1]);
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
return 0;
}

View File

@ -0,0 +1,143 @@
/* Prevent warnings on Visual Studio */
struct _RPC_ASYNC_STATE;
#include "curl/curl.h"
#include <stdlib.h>
#include <string.h>
int GetFtpFile(void)
{
int retVal = 0;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl)
{
/* Get curl 7.9.2 from sunet.se's FTP site: */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
curl_easy_setopt(curl, CURLOPT_URL,
"ftp://public.kitware.com/pub/cmake/cygwin/setup.hint");
res = curl_easy_perform(curl);
if ( res != 0 )
{
printf("Error fetching: ftp://public.kitware.com/pub/cmake/cygwin/setup.hint\n");
retVal = 1;
}
/* always cleanup */
curl_easy_cleanup(curl);
}
else
{
printf("Cannot create curl object\n");
retVal = 1;
}
return retVal;
}
int GetWebFile(void)
{
int retVal = 0;
CURL *curl;
CURLcode res;
char proxy[1024];
int proxy_type = 0;
if ( getenv("HTTP_PROXY") )
{
proxy_type = 1;
if (getenv("HTTP_PROXY_PORT") )
{
sprintf(proxy, "%s:%s", getenv("HTTP_PROXY"), getenv("HTTP_PROXY_PORT"));
}
else
{
sprintf(proxy, "%s", getenv("HTTP_PROXY"));
}
if ( getenv("HTTP_PROXY_TYPE") )
{
/* HTTP/SOCKS4/SOCKS5 */
if ( strcmp(getenv("HTTP_PROXY_TYPE"), "HTTP") == 0 )
{
proxy_type = 1;
}
else if ( strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS4") == 0 )
{
proxy_type = 2;
}
else if ( strcmp(getenv("HTTP_PROXY_TYPE"), "SOCKS5") == 0 )
{
proxy_type = 3;
}
}
}
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
/* Using proxy */
if ( proxy_type > 0 )
{
curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
switch (proxy_type)
{
case 2:
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
break;
case 3:
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
break;
default:
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
}
}
/* get the first document */
curl_easy_setopt(curl, CURLOPT_URL, "http://www.cmake.org/page1.html");
res = curl_easy_perform(curl);
if ( res != 0 )
{
printf("Error fetching: http://www.cmake.org/page1.html\n");
retVal = 1;
}
/* get another document from the same server using the same
connection */
/*
curl_easy_setopt(curl, CURLOPT_URL, "http://www.cmake.org/page2.html");
res = curl_easy_perform(curl);
if ( res != 0 )
{
printf("Error fetching: http://www.cmake.org/page2.html\n");
retVal = 1;
}
*/
/* always cleanup */
curl_easy_cleanup(curl);
}
else
{
printf("Cannot create curl object\n");
retVal = 1;
}
return retVal;
}
int main(/*int argc, char **argv*/)
{
int retVal = 0;
curl_global_init(CURL_GLOBAL_DEFAULT);
retVal += GetWebFile();
/* Do not check the output of FTP socks5 cannot handle FTP yet */
GetFtpFile();
curl_global_cleanup();
return retVal;
}

View File

@ -0,0 +1,83 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include "curl/curl.h"
#include "curl/types.h"
#include "curl/easy.h"
#include "testconfig.h"
/*
* This is an example showing how to get a single file from an FTP server.
* It delays the actual destination file creation until the first write
* callback so that it won't create an empty file in case the remote file
* doesn't exist or something else fails.
*/
struct FtpFile {
char *filename;
FILE *stream;
};
int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
struct FtpFile *out=(struct FtpFile *)stream;
if(out && !out->stream) {
/* open file for writing */
out->stream=fopen(out->filename, "wb");
if(!out->stream)
return -1; /* failure, can't open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
int main(void)
{
CURL *curl;
CURLcode res;
struct FtpFile ftpfile={
LIBCURL_BINARY_DIR "/Testing/ftpget-download.txt", /* name to store the file as if succesful */
NULL
};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/* Get curl 7.9.2 from sunet.se's FTP site: */
curl_easy_setopt(curl, CURLOPT_URL,
"ftp://public.kitware.com/pub/cmake/cygwin/setup.hint");
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_FILE, &ftpfile);
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, TRUE);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
if(CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}
if(ftpfile.stream)
fclose(ftpfile.stream); /* close the local file */
curl_global_cleanup();
return 0;
}

View File

@ -0,0 +1,63 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include "curl/curl.h"
#include "curl/types.h"
#include "curl/easy.h"
#include "testconfig.h"
/*
* Similar to ftpget.c but this also stores the received response-lines
* in a separate file using our own callback!
*
* This functionality was introduced in libcurl 7.9.3.
*/
size_t
write_response(void *ptr, size_t size, size_t nmemb, void *data)
{
FILE *writehere = (FILE *)data;
return fwrite(ptr, size, nmemb, writehere);
}
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *ftpfile;
FILE *respfile;
/* local file name to store the file as */
ftpfile = fopen(LIBCURL_BINARY_DIR "/Testing/ftpgetresp-list.txt", "wb"); /* b is binary, needed on win32 */
/* local file name to store the FTP server's response lines in */
respfile = fopen(LIBCURL_BINARY_DIR "/Testing/ftpgetresp-responses.txt", "wb"); /* b is binary, needed on win32 */
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/* Get a file listing from sunet */
curl_easy_setopt(curl, CURLOPT_URL, "ftp://public.kitware.com/");
curl_easy_setopt(curl, CURLOPT_FILE, ftpfile);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_response);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, respfile);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(ftpfile); /* close the local file */
fclose(respfile); /* close the response file */
return 0;
}

View File

@ -0,0 +1,92 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include "curl/curl.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "testconfig.h"
/*
* This example shows an FTP upload, with a rename of the file just after
* a successful upload.
*
* Example based on source code provided by Erick Nuwendam. Thanks!
*/
#define LOCAL_FILE LIBCURL_SOURCE_DIR "/Testing/ftpupload.c"
#define UPLOAD_FILE_AS "while-uploading.txt"
#define REMOTE_URL "ftp://public.kitware.com/incoming/" UPLOAD_FILE_AS
#define RENAME_FILE_TO "renamed-and-fine.txt"
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *ftpfile;
FILE * hd_src ;
int hd ;
struct stat file_info;
struct curl_slist *headerlist=NULL;
char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
char buf_2 [] = "RNTO " RENAME_FILE_TO;
/* get the file size of the local file */
hd = open(LOCAL_FILE, O_RDONLY) ;
fstat(hd, &file_info);
close(hd) ;
/* get a FILE * of the same file, could also be made with
fdopen() from the previous descriptor, but hey this is just
an example! */
hd_src = fopen(LOCAL_FILE, "rb");
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* build a list of commands to pass to libcurl */
headerlist = curl_slist_append(headerlist, buf_1);
headerlist = curl_slist_append(headerlist, buf_2);
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, TRUE) ;
/* specify target */
curl_easy_setopt(curl,CURLOPT_URL, REMOTE_URL);
/* pass in that last of FTP commands to run after the transfer */
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);
/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_INFILE, hd_src);
/* and give the size of the upload (optional) */
curl_easy_setopt(curl, CURLOPT_INFILESIZE, (long)file_info.st_size);
/* Now run off and do what you've been told! */
res = curl_easy_perform(curl);
/* clean up the FTP commands list */
curl_slist_free_all (headerlist);
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(hd_src); /* close the local file */
curl_global_cleanup();
return 0;
}

View File

@ -0,0 +1,83 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*
* Example source code to show how the callback function can be used to
* download data into a chunk of memory instead of storing it in a file.
*
* This exact source code has not been verified to work.
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include "curl/curl.h"
#include "curl/types.h"
#include "curl/easy.h"
struct MemoryStruct {
char *memory;
size_t size;
};
size_t
WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register int realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory) {
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
return realsize;
}
int main(int argc, char **argv)
{
CURL *curl_handle;
struct MemoryStruct chunk;
chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
chunk.size = 0; /* no data at this point */
curl_global_init(CURL_GLOBAL_DEFAULT);
/* init the curl session */
curl_handle = curl_easy_init();
/* specify URL to get */
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://www.cmake.org/HTML/Index.html");
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl_handle, CURLOPT_FILE, (void *)&chunk);
/* get it! */
curl_easy_perform(curl_handle);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
/*
* Now, our chunk.memory points to a memory block that is chunk.size
* bytes big and contains the remote file.
*
* Do something nice with it!
*/
/* For example display it... */
write(1, chunk.memory, chunk.size);
return 0;
}

View File

@ -0,0 +1,35 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
/* Now specify the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

View File

@ -0,0 +1,100 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>
/*
* This example shows a HTTP PUT operation. PUTs a file given as a command
* line argument to the URL also given on the command line.
*
* This example also uses its own read callback.
*/
size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t retcode;
/* in real-world cases, this would probably get this data differently
as this fread() stuff is exactly what the library already would do
by default internally */
retcode = fread(ptr, size, nmemb, stream);
fprintf(stderr, "*** We read %d bytes from file\n", retcode);
return retcode;
}
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *ftpfile;
FILE * hd_src ;
int hd ;
struct stat file_info;
char *file;
char *url;
if(argc < 3)
return 1;
file= argv[1];
url = argv[2];
/* get the file size of the local file */
hd = open(file, O_RDONLY) ;
fstat(hd, &file_info);
close(hd) ;
/* get a FILE * of the same file, could also be made with
fdopen() from the previous descriptor, but hey this is just
an example! */
hd_src = fopen(file, "rb");
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* we want to use our own read function */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, TRUE) ;
/* HTTP PUT please */
curl_easy_setopt(curl, CURLOPT_PUT, TRUE);
/* specify target */
curl_easy_setopt(curl,CURLOPT_URL, url);
/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_INFILE, hd_src);
/* and give the size of the upload (optional) */
curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_info.st_size);
/* Now run off and do what you've been told! */
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(hd_src); /* close the local file */
curl_global_cleanup();
return 0;
}

View File

@ -0,0 +1,70 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
/* A multi-threaded example that uses pthreads extensively to fetch
* X remote files at once */
#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h>
/* silly list of test-URLs */
char *urls[]= {
"http://curl.haxx.se/",
"ftp://cool.haxx.se/",
"http://www.contactor.se/",
"www.haxx.se"
};
void *pull_one_url(void *url)
{
CURL *curl;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return NULL;
}
/*
int pthread_create(pthread_t *new_thread_ID,
const pthread_attr_t *attr,
void * (*start_func)(void *), void *arg);
*/
int main(int argc, char **argv)
{
pthread_t tid[4];
int i;
int error;
for(i=0; i< 4; i++) {
error = pthread_create(&tid[i],
NULL, /* default attributes please */
pull_one_url,
urls[i]);
if(0 != error)
fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
else
fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
}
/* now wait for all threads to terminate */
for(i=0; i< 4; i++) {
error = pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
}
return 0;
}

View File

@ -0,0 +1,53 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include "curl/curl.h"
/* to make this work under windows, use the win32-functions from the
docs/examples/win32socket.c file as well */
/* This example REQUIRES libcurl 7.7 or later */
#if (LIBCURL_VERSION_NUM < 0x070700)
#error Too old libcurl version, upgrade or stay away.
#endif
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
#ifdef MALLOCDEBUG
/* this sends all memory debug messages to a specified logfile */
curl_memdebug("memdump");
#endif
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
/* get the first document */
curl_easy_setopt(curl, CURLOPT_URL, "http://www.cmake.org/");
res = curl_easy_perform(curl);
/* get another document from the same server using the same
connection */
curl_easy_setopt(curl, CURLOPT_URL, "http://www.cmake.org/HTML/Index.html");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

View File

@ -0,0 +1,92 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*
* Example code that uploads a file name 'foo' to a remote script that accepts
* "HTML form based" (as described in RFC1738) uploads using HTTP POST.
*
* The imaginary form we'll fill in looks like:
*
* <form method="post" enctype="multipart/form-data" action="examplepost.cgi">
* Enter file: <input type="file" name="sendfile" size="40">
* Enter file name: <input type="text" name="filename" size="30">
* <input type="submit" value="send" name="submit">
* </form>
*
* This exact source code has not been verified to work.
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#if LIBCURL_VERSION_NUM < 0x070900
#error "curl_formadd() is not introduced until libcurl 7.9 and later"
#endif
int main(int argc, char *argv[])
{
CURL *curl;
CURLcode res;
struct HttpPost *formpost=NULL;
struct HttpPost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
char buf[] = "Expect:";
/* Fill in the file upload field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, "postit2.c",
CURLFORM_END);
/* Fill in the filename field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, "postit2.c",
CURLFORM_END);
/* Fill in the submit field too, even if this is rarely needed */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "submit",
CURLFORM_COPYCONTENTS, "send",
CURLFORM_END);
curl = curl_easy_init();
/* initalize custom header list (stating that Expect: 100-continue is not
wanted */
headerlist = curl_slist_append(headerlist, buf);
if(curl) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/examplepost.cgi");
if ( (argc == 2) && (!strcmp(argv[1], "noexpectheader")) )
/* only disable 100-continue header if explicitly requested */
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
/* free slist */
curl_slist_free_all (headerlist);
}
return 0;
}

View File

@ -0,0 +1,78 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include "curl/curl.h"
#include "curl/types.h"
#include "curl/easy.h"
#include "testconfig.h"
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
int main(int argc, char **argv)
{
CURL *curl_handle;
char *headerfilename = LIBCURL_BINARY_DIR "/Testing/sepheaders-head.out";
FILE *headerfile;
char *bodyfilename = LIBCURL_BINARY_DIR "/Testing/sepheaders-body.out";
FILE *bodyfile;
curl_global_init(CURL_GLOBAL_DEFAULT);
/* init the curl session */
curl_handle = curl_easy_init();
/* set URL to get */
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://www.cmake.org/HTML/Index.html");
/* no progress meter please */
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
/* shut up completely */
curl_easy_setopt(curl_handle, CURLOPT_MUTE, 1);
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
/* open the files */
headerfile = fopen(headerfilename,"w");
if (headerfile == NULL) {
curl_easy_cleanup(curl_handle);
return -1;
}
bodyfile = fopen(bodyfilename,"w");
if (bodyfile == NULL) {
curl_easy_cleanup(curl_handle);
return -1;
}
/* we want the headers to this file handle */
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER ,headerfile);
/* we want the body to this file handle */
curl_easy_setopt(curl_handle, CURLOPT_FILE ,bodyfile);
/* get it! */
curl_easy_perform(curl_handle);
/* close the header file */
fclose(headerfile);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
return 0;
}

View File

@ -0,0 +1,28 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include "curl/curl.h"
int main(void)
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://www.cmake.org/HTML/Index.html");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

View File

@ -0,0 +1,118 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
/* some requirements for this to work:
1. set pCertFile to the file with the client certificate
2. if the key is passphrase protected, set pPassphrase to the
passphrase you use
3. if you are using a crypto engine:
3.1. set a #define USE_ENGINE
3.2. set pEngine to the name of the crypto engine you use
3.3. set pKeyName to the key identifier you want to use
4. if you don't use a crypto engine:
4.1. set pKeyName to the file name of your client key
4.2. if the format of the key file is DER, set pKeyType to "DER"
!! verify of the server certificate is not implemented here !!
**** This example only works with libcurl 7.9.3 and later! ****
*/
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE *headerfile;
const char *pCertFile = "testcert.pem";
const char *pCACertFile="cacert.pem"
const char *pKeyName;
const char *pKeyType;
const char *pEngine;
#if USE_ENGINE
pKeyName = "rsa_test";
pKeyType = "ENG";
pEngine = "chil"; /* for nChiper HSM... */
#else
pKeyName = "testkey.pem";
pKeyType = "PEM";
pEngine = NULL;
#endif
const char *pPassphrase = NULL;
headerfile = fopen("dumpit", "w");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/* what call to write: */
curl_easy_setopt(curl, CURLOPT_URL, "HTTPS://curl.haxx.se");
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile);
while(1) /* do some ugly short cut... */
{
if (pEngine) /* use crypto engine */
{
if (curl_easy_setopt(curl, CURLOPT_SSLENGINE,pEngine) != CURLE_OK)
{ /* load the crypto engine */
fprintf(stderr,"can't set crypto engine\n");
break;
}
if (curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT,1) != CURLE_OK)
{ /* set the crypto engine as default */
/* only needed for the first time you load
a engine in a curl object... */
fprintf(stderr,"can't set crypto engine as default\n");
break;
}
}
/* cert is stored PEM coded in file... */
/* since PEM is default, we needn't set it for PEM */
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
/* set the cert for client authentication */
curl_easy_setopt(curl,CURLOPT_SSLCERT,pCertFile);
/* sorry, for engine we must set the passphrase
(if the key has one...) */
if (pPassphrase)
curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD,pPassphrase);
/* if we use a key stored in a crypto engine,
we must set the key type to "ENG" */
curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,pKeyType);
/* set the private key (file or ID in engine) */
curl_easy_setopt(curl,CURLOPT_SSLKEY,pKeyName);
/* set the file with the certs vaildating the server */
curl_easy_setopt(curl,CURLOPT_CAINFO,pCACertFile);
/* disconnect if we can't validate server's cert */
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,1);
res = curl_easy_perform(curl);
break; /* we are done... */
}
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}

View File

@ -0,0 +1,7 @@
#ifndef __testconfig_h__
#define __testconfig_h__
#define LIBCURL_SOURCE_DIR "${LIBCURL_SOURCE_DIR}"
#define LIBCURL_BINARY_DIR "${LIBCURL_BINARY_DIR}"
#endif /* __testconfig_h__ */

View File

@ -0,0 +1,49 @@
/*
* Note: This is only required if you use curl 7.8 or lower, later
* versions provide an option to curl_global_init() that does the
* win32 initialization for you.
*/
/*
* These are example functions doing socket init that Windows
* require. If you don't use windows, you can safely ignore this crap.
*/
#include <windows.h>
void win32_cleanup(void)
{
WSACleanup();
}
int win32_init(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return 1;
/* Confirm that the Windows Sockets DLL supports 1.1.*/
/* Note that if the DLL supports versions greater */
/* than 1.1 in addition to 1.1, it will still return */
/* 1.1 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return 1;
}
return 0; /* 0 is ok */
}

View File

@ -0,0 +1,49 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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 "amigaos.h"
#include <stdio.h> /* for stderr */
struct Library *SocketBase = NULL;
void amiga_cleanup()
{
if(SocketBase)
CloseLibrary(SocketBase);
SocketBase = NULL;
}
BOOL amiga_init()
{
if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) {
fprintf(stderr, "No TCP/IP Stack running!\n\a");
return FALSE;
}
atexit(amiga_cleanup);
return TRUE;
}

View File

@ -0,0 +1,52 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef LIBCURL_AMIGAOS_H
#define LIBCURL_AMIGAOS_H
#ifndef __ixemul__
#include <exec/types.h>
#include <exec/execbase.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <bsdsocket.h>
#include "config-amigaos.h"
#define select(args...) WaitSelect( args, NULL)
#define inet_ntoa(x) Inet_NtoA( x ## .s_addr)
#define ioctl(a,b,c,d) IoctlSocket( (LONG)a, (ULONG)b, (char*)c)
#define _AMIGASF 1
extern void amiga_cleanup();
extern BOOL amiga_init();
#else /* __ixemul__ */
#warning compiling with ixemul...
#endif /* __ixemul__ */
#endif /* LIBCURL_AMIGAOS_H */

View File

@ -0,0 +1,101 @@
#ifndef __ARPA_TELNET_H
#define __ARPA_TELNET_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef CURL_DISABLE_TELNET
/*
* Telnet option defines. Add more here if in need.
*/
#define CURL_TELOPT_BINARY 0 /* binary 8bit data */
#define CURL_TELOPT_SGA 3 /* Supress Go Ahead */
#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */
#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */
#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */
#define CURL_NEW_ENV_VAR 0
#define CURL_NEW_ENV_VALUE 1
/*
* The telnet options represented as strings
*/
static const char *telnetoptions[]=
{
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD",
"NAME", "STATUS", "TIMING MARK", "RCTE",
"NAOL", "NAOP", "NAOCRD", "NAOHTS",
"NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD",
"NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
"DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION",
"TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING",
"TTYLOC", "3270 REGIME", "X3 PAD", "NAWS",
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
#define CURL_TELOPT(x) telnetoptions[x]
#define CURL_NTELOPTS 40
/*
* First some defines
*/
#define CURL_xEOF 236 /* End Of File */
#define CURL_SE 240 /* Sub negotiation End */
#define CURL_NOP 241 /* No OPeration */
#define CURL_DM 242 /* Data Mark */
#define CURL_GA 249 /* Go Ahead, reverse the line */
#define CURL_SB 250 /* SuBnegotiation */
#define CURL_WILL 251 /* Our side WILL use this option */
#define CURL_WONT 252 /* Our side WON'T use this option */
#define CURL_DO 253 /* DO use this option! */
#define CURL_DONT 254 /* DON'T use this option! */
#define CURL_IAC 255 /* Interpret As Command */
/*
* Then those numbers represented as strings:
*/
static const char *telnetcmds[]=
{
"EOF", "SUSP", "ABORT", "EOR", "SE",
"NOP", "DMARK", "BRK", "IP", "AO",
"AYT", "EC", "EL", "GA", "SB",
"WILL", "WONT", "DO", "DONT", "IAC"
};
#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */
#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */
#define CURL_TELQUAL_IS 0
#define CURL_TELQUAL_SEND 1
#define CURL_TELQUAL_INFO 2
#define CURL_TELQUAL_NAME 3
#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
#endif
#endif

288
Utilities/cmcurl/base64.c Normal file
View File

@ -0,0 +1,288 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/* Base64 encoding/decoding
*
* Test harnesses down the bottom - compile with -DTEST_ENCODE for
* a program that will read in raw data from stdin and write out
* a base64-encoded version to stdout, and the length returned by the
* encoding function to stderr. Compile with -DTEST_DECODE for a program that
* will go the other way.
*
* This code will break if int is smaller than 32 bits
*/
#include "setup.h"
#include <stdlib.h>
#include <string.h>
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "base64.h"
#include "curl_memory.h"
/* include memdebug.h last */
#include "memdebug.h"
static void decodeQuantum(unsigned char *dest, const char *src)
{
unsigned int x = 0;
int i;
for(i = 0; i < 4; i++) {
if(src[i] >= 'A' && src[i] <= 'Z')
x = (x << 6) + (unsigned int)(src[i] - 'A' + 0);
else if(src[i] >= 'a' && src[i] <= 'z')
x = (x << 6) + (unsigned int)(src[i] - 'a' + 26);
else if(src[i] >= '0' && src[i] <= '9')
x = (x << 6) + (unsigned int)(src[i] - '0' + 52);
else if(src[i] == '+')
x = (x << 6) + 62;
else if(src[i] == '/')
x = (x << 6) + 63;
else if(src[i] == '=')
x = (x << 6);
}
dest[2] = (unsigned char)(x & 255);
x >>= 8;
dest[1] = (unsigned char)(x & 255);
x >>= 8;
dest[0] = (unsigned char)(x & 255);
}
/*
* Curl_base64_decode()
*
* Given a base64 string at src, decode it into the memory pointed to by
* dest. Returns the length of the decoded data.
*/
size_t Curl_base64_decode(const char *src, char *dest)
{
int length = 0;
int equalsTerm = 0;
int i;
int numQuantums;
unsigned char lastQuantum[3];
size_t rawlen;
while((src[length] != '=') && src[length])
length++;
while(src[length+equalsTerm] == '=')
equalsTerm++;
numQuantums = (length + equalsTerm) / 4;
rawlen = (numQuantums * 3) - equalsTerm;
for(i = 0; i < numQuantums - 1; i++) {
decodeQuantum((unsigned char *)dest, src);
dest += 3; src += 4;
}
decodeQuantum(lastQuantum, src);
for(i = 0; i < 3 - equalsTerm; i++)
dest[i] = lastQuantum[i];
return rawlen;
}
/* ---- Base64 Encoding --- */
static char table64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
* Curl_base64_encode()
*
* Returns the length of the newly created base64 string. The third argument
* is a pointer to an allocated area holding the base64 data. If something
* went wrong, -1 is returned.
*
*/
size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
{
unsigned char ibuf[3];
unsigned char obuf[4];
int i;
int inputparts;
char *output;
char *base64data;
char *indata = (char *)inp;
*outptr = NULL; /* set to NULL in case of failure before we reach the end */
if(0 == insize)
insize = strlen(indata);
base64data = output = (char*)malloc(insize*4/3+4);
if(NULL == output)
return 0;
while(insize > 0) {
for (i = inputparts = 0; i < 3; i++) {
if(insize > 0) {
inputparts++;
ibuf[i] = *indata;
indata++;
insize--;
}
else
ibuf[i] = 0;
}
obuf [0] = (ibuf [0] & 0xFC) >> 2;
obuf [1] = ((ibuf [0] & 0x03) << 4) | ((ibuf [1] & 0xF0) >> 4);
obuf [2] = ((ibuf [1] & 0x0F) << 2) | ((ibuf [2] & 0xC0) >> 6);
obuf [3] = ibuf [2] & 0x3F;
switch(inputparts) {
case 1: /* only one byte read */
snprintf(output, 5, "%c%c==",
table64[obuf[0]],
table64[obuf[1]]);
break;
case 2: /* two bytes read */
snprintf(output, 5, "%c%c%c=",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]]);
break;
default:
snprintf(output, 5, "%c%c%c%c",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
table64[obuf[3]] );
break;
}
output += 4;
}
*output=0;
*outptr = base64data; /* make it return the actual data memory */
return strlen(base64data); /* return the length of the new data */
}
/* ---- End of Base64 Encoding ---- */
/************* TEST HARNESS STUFF ****************/
#ifdef TEST_ENCODE
/* encoding test harness. Read in standard input and write out the length
* returned by Curl_base64_encode, followed by the base64'd data itself
*/
#include <stdio.h>
#define TEST_NEED_SUCK
void *suck(int *);
int main(int argc, char **argv, char **envp)
{
char *base64;
size_t base64Len;
unsigned char *data;
int dataLen;
data = (unsigned char *)suck(&dataLen);
base64Len = Curl_base64_encode(data, dataLen, &base64);
fprintf(stderr, "%d\n", base64Len);
fprintf(stdout, "%s", base64);
free(base64); free(data);
return 0;
}
#endif
#ifdef TEST_DECODE
/* decoding test harness. Read in a base64 string from stdin and write out the
* length returned by Curl_base64_decode, followed by the decoded data itself
*
* gcc -DTEST_DECODE base64.c -o base64 mprintf.o memdebug.o
*/
#include <stdio.h>
#define TEST_NEED_SUCK
void *suck(int *);
int main(int argc, char **argv, char **envp)
{
char *base64;
int base64Len;
unsigned char *data;
int dataLen;
int i, j;
base64 = (char *)suck(&base64Len);
data = (unsigned char *)malloc(base64Len * 3/4 + 8);
dataLen = Curl_base64_decode(base64, data);
fprintf(stderr, "%d\n", dataLen);
for(i=0; i < dataLen; i+=0x10) {
printf("0x%02x: ", i);
for(j=0; j < 0x10; j++)
if((j+i) < dataLen)
printf("%02x ", data[i+j]);
else
printf(" ");
printf(" | ");
for(j=0; j < 0x10; j++)
if((j+i) < dataLen)
printf("%c", isgraph(data[i+j])?data[i+j]:'.');
else
break;
puts("");
}
free(base64); free(data);
return 0;
}
#endif
#ifdef TEST_NEED_SUCK
/* this function 'sucks' in as much as possible from stdin */
void *suck(int *lenptr)
{
int cursize = 8192;
unsigned char *buf = NULL;
int lastread;
int len = 0;
do {
cursize *= 2;
buf = (unsigned char *)realloc(buf, cursize);
memset(buf + len, 0, cursize - len);
lastread = fread(buf + len, 1, cursize - len, stdin);
len += lastread;
} while(!feof(stdin));
lenptr[0] = len;
return (void *)buf;
}
#endif

27
Utilities/cmcurl/base64.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef __BASE64_H
#define __BASE64_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
size_t Curl_base64_encode(const char *input, size_t size, char **str);
size_t Curl_base64_decode(const char *source, char *dest);
#endif

View File

@ -0,0 +1 @@
/* ca bundle path set in here*/

View File

@ -0,0 +1,512 @@
/* lib/config.h.in. Generated from configure.in by autoheader. */
/* to disable DICT */
#cmakedefine CURL_DISABLE_DICT ${CURL_DISABLE_DICT}
/* 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}
/* your Entropy Gathering Daemon socket pathname */
#cmakedefine EGD_SOCKET ${EGD_SOCKET}
/* Define if you want to enable IPv6 support */
#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6}
/* Define to 1 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 to 1 if you have the <assert.h> header file. */
#cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H}
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET ${HAVE_CLOSESOCKET}
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA ${HAVE_CRYPTO_CLEANUP_ALL_EX_DATA}
/* Define to 1 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}
/* disabled non-blocking sockets */
#cmakedefine HAVE_DISABLED_NONBLOCKING ${HAVE_DISABLED_NONBLOCKING}
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H}
/* Define to 1 if you have the `dlopen' function. */
#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN}
/* Define to 1 if you have the <err.h> header file. */
#cmakedefine HAVE_ERR_H ${HAVE_ERR_H}
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H}
/* use FIONBIO for non-blocking sockets */
#cmakedefine HAVE_FIONBIO ${HAVE_FIONBIO}
/* Define if getaddrinfo exists and works */
#cmakedefine HAVE_GETADDRINFO ${HAVE_GETADDRINFO}
/* Define to 1 if you have the `geteuid' function. */
#cmakedefine HAVE_GETEUID ${HAVE_GETEUID}
/* Define to 1 if you have the `gethostbyaddr' function. */
#cmakedefine HAVE_GETHOSTBYADDR ${HAVE_GETHOSTBYADDR}
/* If you have gethostbyname */
#cmakedefine HAVE_GETHOSTBYNAME ${HAVE_GETHOSTBYNAME}
/* Define to 1 if you have the `gethostbyname_r' function. */
#cmakedefine HAVE_GETHOSTBYNAME_R ${HAVE_GETHOSTBYNAME_R}
/* gethostbyname_r() takes 3 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_3 ${HAVE_GETHOSTBYNAME_R_3}
/* gethostbyname_r() takes 5 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_5 ${HAVE_GETHOSTBYNAME_R_5}
/* gethostbyname_r() takes 6 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_6 ${HAVE_GETHOSTBYNAME_R_6}
/* Define to 1 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 to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY}
/* we have a glibc-style strerror_r() */
#cmakedefine HAVE_GLIBC_STRERROR_R ${HAVE_GLIBC_STRERROR_R}
/* Define to 1 if you have the `gmtime_r' function. */
#cmakedefine HAVE_GMTIME_R ${HAVE_GMTIME_R}
/* if you have the gssapi libraries */
#cmakedefine HAVE_GSSAPI ${HAVE_GSSAPI}
/* if you have the Heimdal gssapi libraries */
#cmakedefine HAVE_GSSHEIMDAL ${HAVE_GSSHEIMDAL}
/* if you have the MIT gssapi libraries */
#cmakedefine HAVE_GSSMIT ${HAVE_GSSMIT}
/* Define to 1 if you have the `idn_free' function. */
#cmakedefine HAVE_IDN_FREE ${HAVE_IDN_FREE}
/* Define to 1 if you have the <idn-free.h> header file. */
#cmakedefine HAVE_IDN_FREE_H ${HAVE_IDN_FREE_H}
/* Define to 1 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 to 1 if you have the `inet_ntoa_r' function. */
#cmakedefine HAVE_INET_NTOA_R ${HAVE_INET_NTOA_R}
/* inet_ntoa_r() is declared */
#cmakedefine HAVE_INET_NTOA_R_DECL ${HAVE_INET_NTOA_R_DECL}
/* Define to 1 if you have the `inet_pton' function. */
#cmakedefine HAVE_INET_PTON ${HAVE_INET_PTON}
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H}
/* use ioctlsocket() for non-blocking sockets */
#cmakedefine HAVE_IOCTLSOCKET ${HAVE_IOCTLSOCKET}
/* use Ioctlsocket() for non-blocking sockets */
#cmakedefine HAVE_IOCTLSOCKET_CASE ${HAVE_IOCTLSOCKET_CASE}
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H ${HAVE_IO_H}
/* if you have the Kerberos4 libraries (including -ldes) */
#cmakedefine HAVE_KRB4 ${HAVE_KRB4}
/* 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 to 1 if you have the <krb.h> header file. */
#cmakedefine HAVE_KRB_H ${HAVE_KRB_H}
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#cmakedefine HAVE_LIBCRYPTO ${HAVE_LIBCRYPTO}
/* Define to 1 if you have the `dl' library (-ldl). */
#cmakedefine HAVE_LIBDL ${HAVE_LIBDL}
/* Define to 1 if you have the `idn' library (-lidn). */
#cmakedefine HAVE_LIBIDN ${HAVE_LIBIDN}
/* Define to 1 if you have the `resolv' library (-lresolv). */
#cmakedefine HAVE_LIBRESOLV ${HAVE_LIBRESOLV}
/* Define to 1 if you have the `resolve' library (-lresolve). */
#cmakedefine HAVE_LIBRESOLVE ${HAVE_LIBRESOLVE}
/* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET ${HAVE_LIBSOCKET}
/* Define to 1 if you have the `ssl' library (-lssl). */
#cmakedefine HAVE_LIBSSL ${HAVE_LIBSSL}
/* if zlib is available */
#cmakedefine HAVE_LIBZ ${HAVE_LIBZ}
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H}
/* Define to 1 if you have the `localtime_r' function. */
#cmakedefine HAVE_LOCALTIME_R ${HAVE_LOCALTIME_R}
/* if your compiler supports 'long long' */
#cmakedefine HAVE_LONGLONG ${HAVE_LONGLONG}
/* 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/in.h> header file. */
#cmakedefine HAVE_NETINET_IN_H ${HAVE_NETINET_IN_H}
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#cmakedefine HAVE_NETINET_TCP_H ${HAVE_NETINET_TCP_H}
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H ${HAVE_NET_IF_H}
/* Define if NI_WITHSCOPEID exists and works */
#cmakedefine HAVE_NI_WITHSCOPEID ${HAVE_NI_WITHSCOPEID}
/* we have no strerror_r() proto */
#cmakedefine HAVE_NO_STRERROR_R_DECL ${HAVE_NO_STRERROR_R_DECL}
/* Define to 1 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/engine.h> header file. */
#cmakedefine HAVE_OPENSSL_ENGINE_H ${HAVE_OPENSSL_ENGINE_H}
/* Define to 1 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 <openssl/pem.h> header file. */
#cmakedefine HAVE_OPENSSL_PEM_H ${HAVE_OPENSSL_PEM_H}
/* Define to 1 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 <openssl/ssl.h> header file. */
#cmakedefine HAVE_OPENSSL_SSL_H ${HAVE_OPENSSL_SSL_H}
/* Define to 1 if you have the <openssl/x509.h> header file. */
#cmakedefine HAVE_OPENSSL_X509_H ${HAVE_OPENSSL_X509_H}
/* use O_NONBLOCK for non-blocking sockets */
#cmakedefine HAVE_O_NONBLOCK ${HAVE_O_NONBLOCK}
/* Define to 1 if you have the <pem.h> header file. */
#cmakedefine HAVE_PEM_H ${HAVE_PEM_H}
/* Define to 1 if you have the `perror' function. */
#cmakedefine HAVE_PERROR ${HAVE_PERROR}
/* Define to 1 if you have the `poll' function. */
#cmakedefine HAVE_POLL ${HAVE_POLL}
/* If you have a fine poll */
#cmakedefine HAVE_POLL_FINE ${HAVE_POLL_FINE}
/* we have a POSIX-style strerror_r() */
#cmakedefine HAVE_POSIX_STRERROR_R ${HAVE_POSIX_STRERROR_R}
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H ${HAVE_PWD_H}
/* Define to 1 if you have the `RAND_egd' function. */
#cmakedefine HAVE_RAND_EGD ${HAVE_RAND_EGD}
/* Define to 1 if you have the `RAND_screen' function. */
#cmakedefine HAVE_RAND_SCREEN ${HAVE_RAND_SCREEN}
/* Define to 1 if you have the `RAND_status' function. */
#cmakedefine HAVE_RAND_STATUS ${HAVE_RAND_STATUS}
/* Define to 1 if you have the <rsa.h> header file. */
#cmakedefine HAVE_RSA_H ${HAVE_RSA_H}
/* Define to 1 if you have the `select' function. */
#cmakedefine HAVE_SELECT ${HAVE_SELECT}
/* Define to 1 if you have the <setjmp.h> header file. */
#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H}
/* Define to 1 if you have the <sgtty.h> header file. */
#cmakedefine HAVE_SGTTY_H ${HAVE_SGTTY_H}
/* Define to 1 if you have the `sigaction' function. */
#cmakedefine HAVE_SIGACTION ${HAVE_SIGACTION}
/* Define to 1 if you have the `siginterrupt' function. */
#cmakedefine HAVE_SIGINTERRUPT ${HAVE_SIGINTERRUPT}
/* Define to 1 if you have the `signal' function. */
#cmakedefine HAVE_SIGNAL ${HAVE_SIGNAL}
/* If you have sigsetjmp */
#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP}
/* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET ${HAVE_SOCKET}
/* use SO_NONBLOCK for non-blocking sockets */
#cmakedefine HAVE_SO_NONBLOCK ${HAVE_SO_NONBLOCK}
/* Define this if you have the SPNEGO library fbopenssl */
#cmakedefine HAVE_SPNEGO ${HAVE_SPNEGO}
/* Define to 1 if you have the <ssl.h> header file. */
#cmakedefine HAVE_SSL_H ${HAVE_SSL_H}
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H}
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H}
/* Define to 1 if you have the `strcasecmp' function. */
#cmakedefine HAVE_STRCASECMP ${HAVE_STRCASECMP}
/* Define to 1 if you have the `strcmpi' function. */
#cmakedefine HAVE_STRCMPI ${HAVE_STRCMPI}
/* Define to 1 if you have the `strdup' function. */
#cmakedefine HAVE_STRDUP ${HAVE_STRDUP}
/* Define to 1 if you have the `strerror_r' function. */
#cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R}
/* Define to 1 if you have the `strftime' function. */
#cmakedefine HAVE_STRFTIME ${HAVE_STRFTIME}
/* Define to 1 if you have the `stricmp' function. */
#cmakedefine HAVE_STRICMP ${HAVE_STRICMP}
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H}
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H ${HAVE_STRING_H}
/* Define to 1 if you have the `strlcat' function. */
#cmakedefine HAVE_STRLCAT ${HAVE_STRLCAT}
/* Define to 1 if you have the `strlcpy' function. */
#cmakedefine HAVE_STRLCPY ${HAVE_STRLCPY}
/* Define to 1 if you have the `strstr' function. */
#cmakedefine HAVE_STRSTR ${HAVE_STRSTR}
/* Define to 1 if you have the `strtok_r' function. */
#cmakedefine HAVE_STRTOK_R ${HAVE_STRTOK_R}
/* Define to 1 if you have the `strtoll' function. */
#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL}
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H ${HAVE_SYS_IOCTL_H}
/* Define to 1 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/poll.h> header file. */
#cmakedefine HAVE_SYS_POLL_H ${HAVE_SYS_POLL_H}
/* Define to 1 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 to 1 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 to 1 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 to 1 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 to 1 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 to 1 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 to 1 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 to 1 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 to 1 if you have the <winsock.h> header file. */
#cmakedefine HAVE_WINSOCK_H ${HAVE_WINSOCK_H}
/* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV ${HAVE_WRITABLE_ARGV}
/* Define to 1 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}
/* need REENTRANT defined */
#cmakedefine NEED_REENTRANT ${NEED_REENTRANT}
/* cpu-machine-OS */
#define OS "${OPERATING_SYSTEM}"
/* Name of 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}
/* Define to the type of arg 1 for `select'. */
#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1}
/* Define to the type of args 2, 3 and 4 for `select'. */
#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234}
/* Define to the type of arg 5 for `select'. */
#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5}
/* The size of a `curl_off_t', as computed by sizeof. */
#cmakedefine SIZEOF_CURL_OFF_T ${SIZEOF_CURL_OFF_T}
/* The size of a `size_t', as computed by sizeof. */
#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS ${STDC_HEADERS}
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#cmakedefine TIME_WITH_SYS_TIME ${TIME_WITH_SYS_TIME}
/* Define if you want to enable ares support */
#cmakedefine USE_ARES ${USE_ARES}
/* If you want to build curl with the built-in manual */
#cmakedefine USE_MANUAL ${USE_MANUAL}
/* Version number of package */
#cmakedefine VERSION "${VERSION}"
/* Define to 1 if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
#cmakedefine _ALL_SOURCE ${_ALL_SOURCE}
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
/* Define for large files, on AIX-style hosts. */
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
/* Define to empty if `const' does not conform to ANSI C. */
#cmakedefine const ${const}
/* type to use in place of in_addr_t if not defined */
#cmakedefine in_addr_t ${in_addr_t}
/* Define to `unsigned' if <sys/types.h> does not define. */
#cmakedefine size_t ${size_t}
/* type to use in place of socklen_t if not defined */
#cmakedefine socklen_t ${socklen_t}
/* the signed version of size_t */
#cmakedefine ssize_t ${ssize_t}
/* define if the compiler supports number 0x3627676LL */
#cmakedefine HAVE_LONG_LONG_CONSTANT ${HAVE_LONG_LONG_CONSTANT}
/* Special handling of zlib library */
#cmakedefine CURL_SPECIAL_ZLIB_H "${CURL_SPECIAL_ZLIB_H}"

788
Utilities/cmcurl/connect.c Normal file
View File

@ -0,0 +1,788 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#ifndef WIN32
/* headers for non-win32 */
#include <sys/time.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> /* <netinet/tcp.h> may need it */
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h> /* for TCP_NODELAY */
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototype, without it, this crashes
on macos 68K */
#endif
#if (defined(HAVE_FIONBIO) && defined(__NOVELL_LIBC__))
#include <sys/filio.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#endif
#endif
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifdef WIN32
#include <windows.h>
#define EINPROGRESS WSAEINPROGRESS
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EISCONN WSAEISCONN
#define ENOTSOCK WSAENOTSOCK
#define ECONNREFUSED WSAECONNREFUSED
#endif
#include "urldata.h"
#include "sendf.h"
#include "if2ip.h"
#include "strerror.h"
#include "connect.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
static bool verifyconnect(curl_socket_t sockfd, int *error);
static curl_socket_t
singleipconnect(struct connectdata *conn,
Curl_addrinfo *ai, /* start connecting to this */
long timeout_ms,
bool *connected);
/*
* Curl_ourerrno() returns the errno (or equivalent) on this platform to
* hide platform specific for the function that calls this.
*/
int Curl_ourerrno(void)
{
#ifdef WIN32
return (int)GetLastError();
#else
return errno;
#endif
}
/*
* Curl_nonblock() set the given socket to either blocking or non-blocking
* mode based on the 'nonblock' boolean argument. This function is highly
* portable.
*/
int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */)
{
#undef SETBLOCK
#ifdef HAVE_O_NONBLOCK
{
/* most recent unix versions */
int flags;
flags = fcntl(sockfd, F_GETFL, 0);
if (TRUE == nonblock)
return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
else
return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
}
#define SETBLOCK 1
#endif
#ifdef HAVE_FIONBIO
{
/* older unix versions */
int flags;
flags = nonblock;
return ioctl(sockfd, FIONBIO, &flags);
}
#ifdef SETBLOCK
# undef SETBLOCK
#endif
#define SETBLOCK 2
#endif
#ifdef HAVE_IOCTLSOCKET
/* Windows? */
unsigned long flags;
flags = nonblock;
return ioctlsocket(sockfd, FIONBIO, &flags);
#define SETBLOCK 3
#endif
#ifdef HAVE_IOCTLSOCKET_CASE
/* presumably for Amiga */
return IoctlSocket(sockfd, FIONBIO, (long)nonblock);
#ifdef SETBLOCK
# undef SETBLOCK
#endif
#define SETBLOCK 4
#endif
#ifdef HAVE_SO_NONBLOCK
/* BeOS */
long b = nonblock ? 1 : 0;
return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
#ifdef SETBLOCK
# undef SETBLOCK
#endif
#define SETBLOCK 5
#endif
#ifdef HAVE_DISABLED_NONBLOCKING
(void)nonblock;
(void)sockfd;
return 0; /* returns success */
#ifdef SETBLOCK
# undef SETBLOCK
#endif
#define SETBLOCK 6
#endif
#ifndef SETBLOCK
#error "no non-blocking method was found/used/set"
#endif
}
/*
* waitconnect() waits for a TCP connect on the given socket for the specified
* number if milliseconds. It returns:
* 0 fine connect
* -1 select() error
* 1 select() timeout
* 2 select() returned with an error condition fd_set
*/
#define WAITCONN_CONNECTED 0
#define WAITCONN_SELECT_ERROR -1
#define WAITCONN_TIMEOUT 1
#define WAITCONN_FDSET_ERROR 2
static
int waitconnect(curl_socket_t sockfd, /* socket */
long timeout_msec)
{
fd_set fd;
fd_set errfd;
struct timeval interval;
int rc;
#ifdef mpeix
/* Call this function once now, and ignore the results. We do this to
"clear" the error state on the socket so that we can later read it
reliably. This is reported necessary on the MPE/iX operating system. */
verifyconnect(sockfd, NULL);
#endif
/* now select() until we get connect or timeout */
FD_ZERO(&fd);
FD_SET(sockfd, &fd);
FD_ZERO(&errfd);
FD_SET(sockfd, &errfd);
interval.tv_sec = (int)(timeout_msec/1000);
timeout_msec -= interval.tv_sec*1000;
interval.tv_usec = timeout_msec*1000;
rc = select(sockfd+1, NULL, &fd, &errfd, &interval);
if(-1 == rc)
/* error, no connect here, try next */
return WAITCONN_SELECT_ERROR;
else if(0 == rc)
/* timeout, no connect today */
return WAITCONN_TIMEOUT;
if(FD_ISSET(sockfd, &errfd))
/* error condition caught */
return WAITCONN_FDSET_ERROR;
/* we have a connect! */
return WAITCONN_CONNECTED;
}
static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd)
{
#ifdef HAVE_INET_NTOA
bool bindworked = FALSE;
struct SessionHandle *data = conn->data;
/*************************************************************
* Select device to bind socket to
*************************************************************/
if (strlen(data->set.device)<255) {
struct Curl_dns_entry *h=NULL;
char myhost[256] = "";
in_addr_t in;
int rc;
bool was_iface = FALSE;
/* First check if the given name is an IP address */
in=inet_addr(data->set.device);
if((in == CURL_INADDR_NONE) &&
Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
/*
* We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer
*/
rc = Curl_resolv(conn, myhost, 0, &h);
if(rc == CURLRESOLV_PENDING)
(void)Curl_wait_for_resolv(conn, &h);
if(h)
was_iface = TRUE;
}
if(!was_iface) {
/*
* This was not an interface, resolve the name as a host name
* or IP number
*/
rc = Curl_resolv(conn, data->set.device, 0, &h);
if(rc == CURLRESOLV_PENDING)
(void)Curl_wait_for_resolv(conn, &h);
if(h)
/* we know data->set.device is shorter than the myhost array */
strcpy(myhost, data->set.device);
}
if(! *myhost) {
/* need to fix this
h=Curl_gethost(data,
getmyhost(*myhost,sizeof(myhost)),
hostent_buf,
sizeof(hostent_buf));
*/
failf(data, "Couldn't bind to '%s'", data->set.device);
return CURLE_HTTP_PORT_FAILED;
}
infof(data, "We bind local end to %s\n", myhost);
#ifdef SO_BINDTODEVICE
/* I am not sure any other OSs than Linux that provide this feature, and
* at the least I cannot test. --Ben
*
* This feature allows one to tightly bind the local socket to a
* particular interface. This will force even requests to other local
* interfaces to go out the external interface.
*
*/
if (was_iface) {
/* Only bind to the interface when specified as interface, not just as a
* hostname or ip address.
*/
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
data->set.device, strlen(data->set.device)+1) != 0) {
/* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n",
sockfd, data->set.device, Curl_strerror(Curl_ourerrno())); */
infof(data, "SO_BINDTODEVICE %s failed\n",
data->set.device);
/* This is typically "errno 1, error: Operation not permitted" if
you're not running as root or another suitable privileged user */
}
}
#endif
in=inet_addr(myhost);
if (CURL_INADDR_NONE != in) {
if ( h ) {
Curl_addrinfo *addr = h->addr;
Curl_resolv_unlock(data, h);
/* we don't need it anymore after this function has returned */
if( bind(sockfd, addr->ai_addr, (socklen_t)addr->ai_addrlen) >= 0) {
/* we succeeded to bind */
#ifdef ENABLE_IPV6
struct sockaddr_in6 add;
#else
struct sockaddr_in add;
#endif
#ifdef __hpux
int gsize = sizeof(add);
#else
socklen_t gsize = sizeof(add);
#endif
bindworked = TRUE;
if(getsockname(sockfd, (struct sockaddr *) &add,
&gsize)<0) {
failf(data, "getsockname() failed");
return CURLE_HTTP_PORT_FAILED;
}
}
if(!bindworked) {
failf(data, "%s", Curl_strerror(conn, Curl_ourerrno()));
return CURLE_HTTP_PORT_FAILED;
}
} /* end of if h */
else {
failf(data,"could't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
}
} /* end of inet_addr */
else {
failf(data, "could't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
}
return CURLE_OK;
} /* end of device selection support */
#endif /* end of HAVE_INET_NTOA */
return CURLE_HTTP_PORT_FAILED;
}
/*
* verifyconnect() returns TRUE if the connect really has happened.
*/
static bool verifyconnect(curl_socket_t sockfd, int *error)
{
bool rc;
#ifdef SO_ERROR
int err = 0;
#ifdef __hpux
int errSize = sizeof(err);
#else
socklen_t errSize = sizeof(err);
#endif
#ifdef WIN32
/*
* In October 2003 we effectively nullified this function on Windows due to
* problems with it using all CPU in multi-threaded cases.
*
* In May 2004, we bring it back to offer more info back on connect failures.
* Gisle Vanem could reproduce the former problems with this function, but
* could avoid them by adding this SleepEx() call below:
*
* "I don't have Rational Quantify, but the hint from his post was
* ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe
* just Sleep(0) would be enough?) would release whatever
* mutex/critical-section the ntdll call is waiting on.
*
* Someone got to verify this on Win-NT 4.0, 2000."
*/
SleepEx(0, FALSE);
#endif
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
(void *)&err, &errSize))
err = Curl_ourerrno();
if ((0 == err) || (EISCONN == err))
/* we are connected, awesome! */
rc = TRUE;
else
/* This wasn't a successful connect */
rc = FALSE;
if (error)
*error = err;
#else
(void)sockfd;
if (error)
*error = Curl_ourerrno();
#endif
return rc;
}
/* Used within the multi interface. Try next IP address, return TRUE if no
more address exists */
static bool trynextip(struct connectdata *conn,
int sockindex,
bool *connected)
{
curl_socket_t sockfd;
Curl_addrinfo *ai;
if(sockindex != FIRSTSOCKET)
return TRUE; /* no next */
/* try the next address */
ai = conn->ip_addr->ai_next;
while (ai) {
sockfd = singleipconnect(conn, ai, 0L, connected);
if(sockfd != CURL_SOCKET_BAD) {
/* store the new socket descriptor */
conn->sock[sockindex] = sockfd;
conn->ip_addr = ai;
return FALSE;
}
ai = ai->ai_next;
}
return TRUE;
}
/*
* Curl_is_connected() is used from the multi interface to check if the
* firstsocket has connected.
*/
CURLcode Curl_is_connected(struct connectdata *conn,
int sockindex,
bool *connected)
{
int rc;
struct SessionHandle *data = conn->data;
CURLcode code = CURLE_OK;
curl_socket_t sockfd = conn->sock[sockindex];
long allow = DEFAULT_CONNECT_TIMEOUT;
long has_passed;
curlassert(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
*connected = FALSE; /* a very negative world view is best */
/* Evaluate in milliseconds how much time that has passed */
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)
allow = data->set.timeout*1000;
else
allow = data->set.connecttimeout*1000;
}
else if(data->set.timeout) {
allow = data->set.timeout*1000;
}
else if(data->set.connecttimeout) {
allow = data->set.connecttimeout*1000;
}
if(has_passed > allow ) {
/* time-out, bail out, go home */
failf(data, "Connection time-out after %ld ms", has_passed);
return CURLE_OPERATION_TIMEOUTED;
}
if(conn->bits.tcpconnect) {
/* we are connected already! */
*connected = TRUE;
return CURLE_OK;
}
/* check for connect without timeout as we want to return immediately */
rc = waitconnect(sockfd, 0);
if(WAITCONN_CONNECTED == rc) {
if (verifyconnect(sockfd, NULL)) {
/* we are connected, awesome! */
*connected = TRUE;
return CURLE_OK;
}
/* nope, not connected for real */
infof(data, "Connection failed\n");
if(trynextip(conn, sockindex, connected)) {
code = CURLE_COULDNT_CONNECT;
}
}
else if(WAITCONN_TIMEOUT != rc) {
/* nope, not connected */
infof(data, "Connection failed\n");
if(trynextip(conn, sockindex, connected)) {
int error = Curl_ourerrno();
failf(data, "Failed connect to %s:%d; %s",
conn->host.name, conn->port, Curl_strerror(conn,error));
code = CURLE_COULDNT_CONNECT;
}
}
/*
* If the connection failed here, we should attempt to connect to the "next
* address" for the given host.
*/
return code;
}
static void tcpnodelay(struct connectdata *conn,
curl_socket_t sockfd)
{
#ifdef TCP_NODELAY
struct SessionHandle *data= conn->data;
socklen_t onoff = (socklen_t) data->set.tcp_nodelay;
if(setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(conn, Curl_ourerrno()));
else
infof(data,"TCP_NODELAY set\n");
#else
(void)conn;
(void)sockfd;
#endif
}
/* singleipconnect() connects to the given IP only, and it may return without
having connected if used from the multi interface. */
static curl_socket_t
singleipconnect(struct connectdata *conn,
Curl_addrinfo *ai,
long timeout_ms,
bool *connected)
{
char addr_buf[128];
int rc;
int error;
bool conected;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (sockfd == CURL_SOCKET_BAD)
return CURL_SOCKET_BAD;
*connected = FALSE; /* default is not connected */
Curl_printable_address(ai, addr_buf, sizeof(addr_buf));
infof(data, " Trying %s... ", addr_buf);
if(data->set.tcp_nodelay)
tcpnodelay(conn, sockfd);
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);
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
if(-1 == rc) {
error = Curl_ourerrno();
switch (error) {
case EINPROGRESS:
case EWOULDBLOCK:
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
/* On some platforms EAGAIN and EWOULDBLOCK are the
* same value, and on others they are different, hence
* the odd #if
*/
case EAGAIN:
#endif
rc = waitconnect(sockfd, timeout_ms);
break;
default:
/* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect to %s: %s",
addr_buf, Curl_strerror(conn,error));
break;
}
}
/* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
connect(). We can be sure of this since connect() cannot return 1. */
if((WAITCONN_TIMEOUT == rc) &&
(data->state.used_interface == Curl_if_multi)) {
/* Timeout when running the multi interface */
return sockfd;
}
conected = verifyconnect(sockfd, &error);
if(!rc && conected) {
/* we are connected, awesome! */
*connected = TRUE; /* this is a true connect */
infof(data, "connected\n");
return sockfd;
}
else if(WAITCONN_TIMEOUT == rc)
infof(data, "Timeout\n");
else
infof(data, "%s\n", Curl_strerror(conn, error));
/* connect failed or timed out */
sclose(sockfd);
return CURL_SOCKET_BAD;
}
/*
* 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 */
struct Curl_dns_entry *remotehost, /* use this one */
curl_socket_t *sockconn, /* the connected socket */
Curl_addrinfo **addr, /* the one we used */
bool *connected) /* really connected? */
{
struct SessionHandle *data = conn->data;
curl_socket_t sockfd = CURL_SOCKET_BAD;
int aliasindex;
int num_addr;
Curl_addrinfo *ai;
Curl_addrinfo *curr_addr;
struct timeval after;
struct timeval before = Curl_tvnow();
/*************************************************************
* Figure out what maximum time we have left
*************************************************************/
long timeout_ms= DEFAULT_CONNECT_TIMEOUT;
long timeout_per_addr;
*connected = FALSE; /* default to not connected */
if(data->set.timeout || data->set.connecttimeout) {
long has_passed;
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
/* get the most strict timeout of the ones converted to milliseconds */
if(data->set.timeout && data->set.connecttimeout) {
if (data->set.timeout < data->set.connecttimeout)
timeout_ms = data->set.timeout*1000;
else
timeout_ms = data->set.connecttimeout*1000;
}
else if(data->set.timeout)
timeout_ms = data->set.timeout*1000;
else
timeout_ms = data->set.connecttimeout*1000;
/* subtract the passed time */
timeout_ms -= has_passed;
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEOUTED;
}
}
/* Max time for each address */
num_addr = Curl_num_addresses(remotehost->addr);
timeout_per_addr = timeout_ms / num_addr;
ai = remotehost->addr;
/* Below is the loop that attempts to connect to all IP-addresses we
* know for the given host. One by one until one IP succeeds.
*/
if(data->state.used_interface == Curl_if_multi)
/* don't hang when doing multi */
timeout_per_addr = timeout_ms = 0;
/*
* Connecting with a Curl_addrinfo chain
*/
for (curr_addr = ai, aliasindex=0; curr_addr;
curr_addr = curr_addr->ai_next, aliasindex++) {
/* start connecting to the IP curr_addr points to */
sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected);
if(sockfd != CURL_SOCKET_BAD)
break;
/* get a new timeout for next attempt */
after = Curl_tvnow();
timeout_ms -= Curl_tvdiff(after, before);
if(timeout_ms < 0) {
failf(data, "connect() timed out!");
return CURLE_OPERATION_TIMEOUTED;
}
before = after;
} /* end of connect-to-each-address loop */
if (sockfd == CURL_SOCKET_BAD) {
/* no good connect was made */
*sockconn = CURL_SOCKET_BAD;
return CURLE_COULDNT_CONNECT;
}
/* leave the socket in non-blocking mode */
/* store the address we use */
if(addr)
*addr = curr_addr;
/* allow NULL-pointers to get passed in */
if(sockconn)
*sockconn = sockfd; /* the socket descriptor we've connected */
return CURLE_OK;
}

View File

@ -0,0 +1,44 @@
#ifndef __CONNECT_H
#define __CONNECT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */);
CURLcode Curl_is_connected(struct connectdata *conn,
int sockindex,
bool *connected);
CURLcode Curl_connecthost(struct connectdata *conn,
struct Curl_dns_entry *host, /* connect to this */
curl_socket_t *sockconn, /* not set if error */
Curl_addrinfo **addr, /* the one we used */
bool *connected /* truly connected? */
);
int Curl_ourerrno(void);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
#endif

View File

@ -0,0 +1,363 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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 <stdlib.h>
#include <string.h>
#include "urldata.h"
#include <curl/curl.h>
#include "sendf.h"
#include "content_encoding.h"
#include "curl_memory.h"
#include "memdebug.h"
#define DSIZ 0x10000 /* buffer size for decompressed data */
#define GZIP_MAGIC_0 0x1f
#define GZIP_MAGIC_1 0x8b
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
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 */
CURLcode result = CURLE_OK; /* 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;
z->next_in = NULL;
z->avail_in = 0;
if (inflateInit(z) != Z_OK)
return process_zlib_error(data, z);
k->zlib_init = 1;
}
/* Set the compressed input when this function is called */
z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)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) {
if (DSIZ - z->avail_out) {
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));
}
}
}
/* Skip over the gzip header */
static enum {
GZIP_OK,
GZIP_BAD,
GZIP_UNDERFLOW
} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
{
int method, flags;
const ssize_t totallen = len;
/* The shortest header is 10 bytes */
if (len < 10)
return GZIP_UNDERFLOW;
if ((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
return GZIP_BAD;
method = data[2];
flags = data[3];
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
/* Can't handle this compression method or unknown flag */
return GZIP_BAD;
}
/* Skip over time, xflags, OS code and all previous bytes */
len -= 10;
data += 10;
if (flags & EXTRA_FIELD) {
ssize_t extra_len;
if (len < 2)
return GZIP_UNDERFLOW;
extra_len = (data[1] << 8) | data[0];
if (len < (extra_len+2))
return GZIP_UNDERFLOW;
len -= (extra_len + 2);
}
if (flags & ORIG_NAME) {
/* Skip over NUL-terminated file name */
while (len && *data) {
--len;
++data;
}
if (!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
++data;
}
if (flags & COMMENT) {
/* Skip over NUL-terminated comment */
while (len && *data) {
--len;
++data;
}
if (!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
++data;
}
if (flags & HEAD_CRC) {
if (len < 2)
return GZIP_UNDERFLOW;
len -= 2;
data += 2;
}
*headerlen = totallen - len;
return GZIP_OK;
}
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread)
{
int status; /* zlib status */
CURLcode result = CURLE_OK; /* 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;
z->next_in = NULL;
z->avail_in = 0;
if (inflateInit2(z, -MAX_WBITS) != Z_OK)
return process_zlib_error(data, z);
k->zlib_init = 1; /* Initial call state */
}
/* This next mess is to get around the potential case where there isn't
* enough data passed in to skip over the gzip header. If that happens, we
* malloc a block and copy what we have then wait for the next call. If
* there still isn't enough (this is definitely a worst-case scenario), we
* make the block bigger, copy the next part in and keep waiting.
*/
/* Skip over gzip header? */
if (k->zlib_init == 1) {
/* Initial call state */
ssize_t hlen;
switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
case GZIP_OK:
z->next_in = (Bytef *)k->str + hlen;
z->avail_in = (uInt)(nread - hlen);
k->zlib_init = 3; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We need more data so we can find the end of the gzip header. It's
* possible that the memory block we malloc here will never be freed if
* the transfer abruptly aborts after this point. Since it's unlikely
* that circumstances will be right for this code path to be followed in
* the first place, and it's even more unlikely for a transfer to fail
* immediately afterwards, it should seldom be a problem.
*/
z->avail_in = (uInt)nread;
z->next_in = malloc(z->avail_in);
if (z->next_in == NULL) {
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
memcpy(z->next_in, k->str, z->avail_in);
k->zlib_init = 2; /* Need more gzip header data state */
/* We don't have any data to inflate yet */
return CURLE_OK;
case GZIP_BAD:
default:
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
else if (k->zlib_init == 2) {
/* Need more gzip header data state */
ssize_t hlen;
unsigned char *oldblock = z->next_in;
z->avail_in += nread;
z->next_in = realloc(z->next_in, z->avail_in);
if (z->next_in == NULL) {
free(oldblock);
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
memcpy(z->next_in + z->avail_in - nread, k->str, nread);
switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
case GZIP_OK:
/* This is the zlib stream data */
free(z->next_in);
/* Don't point into the malloced block since we just freed it */
z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in;
z->avail_in = (uInt)(z->avail_in - hlen);
k->zlib_init = 3; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We still don't have any data to inflate! */
return CURLE_OK;
case GZIP_BAD:
default:
free(z->next_in);
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
else {
/* Inflating stream state */
z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)nread;
}
if (z->avail_in == 0) {
/* We don't have any data to inflate; wait until next time */
return CURLE_OK;
}
/* 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) {
if(DSIZ - z->avail_out) {
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 */
/* We should really check the gzip CRC here */
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 */

View File

@ -0,0 +1,41 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
/*
* Comma-separated list all supported Content-Encodings ('identity' is implied)
*/
#ifdef HAVE_LIBZ
#define ALL_CONTENT_ENCODINGS "deflate, gzip"
#else
#define ALL_CONTENT_ENCODINGS "identity"
#endif
CURLcode Curl_unencode_deflate_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread);
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread);

879
Utilities/cmcurl/cookie.c Normal file
View File

@ -0,0 +1,879 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/***
RECEIVING COOKIE INFORMATION
============================
struct CookieInfo *cookie_init(char *file);
Inits a cookie struct to store data in a local file. This is always
called before any cookies are set.
int cookies_set(struct CookieInfo *cookie, char *cookie_line);
The 'cookie_line' parameter is a full "Set-cookie:" line as
received from a server.
The function need to replace previously stored lines that this new
line superceeds.
It may remove lines that are expired.
It should return an indication of success/error.
SENDING COOKIE INFORMATION
==========================
struct Cookies *cookie_getlist(struct CookieInfo *cookie,
char *host, char *path, bool secure);
For a given host and path, return a linked list of cookies that
the client should send to the server if used now. The secure
boolean informs the cookie if a secure connection is achieved or
not.
It shall only return cookies that haven't expired.
Example set of cookies:
Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
domain=.fidelity.com; path=/ftgw; secure
Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
domain=.fidelity.com; path=/; secure
Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
domain=.fidelity.com; path=/; secure
Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
domain=.fidelity.com; path=/; secure
Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
domain=.fidelity.com; path=/; secure
Set-cookie:
Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday,
13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
****/
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "urldata.h"
#include "cookie.h"
#include "getdate.h"
#include "strequal.h"
#include "strtok.h"
#include "sendf.h"
#include "curl_memory.h"
/* The last #include file should be: */
#ifdef CURLDEBUG
#include "memdebug.h"
#endif
static void freecookie(struct Cookie *co)
{
if(co->expirestr)
free(co->expirestr);
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);
}
static bool tailmatch(const char *little, const char *bigone)
{
size_t littlelen = strlen(little);
size_t biglen = strlen(bigone);
if(littlelen > biglen)
return FALSE;
return (bool)strequal(little, bigone+biglen-littlelen);
}
/****************************************************************************
*
* Curl_cookie_add()
*
* Add a single cookie line to the cookie keeping object.
*
***************************************************************************/
struct Cookie *
Curl_cookie_add(struct SessionHandle *data,
/* The 'data' pointer here may be NULL at times, and thus
must only be used very carefully for things that can deal
with data being NULL. Such as infof() and similar */
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
char *lineptr, /* first character of the line */
char *domain, /* default domain */
char *path) /* full path used when this cookie is set,
used to get default path for the cookie
unless set */
{
struct Cookie *clist;
char *what;
char name[MAX_NAME];
char *ptr;
char *semiptr;
struct Cookie *co;
struct Cookie *lastc=NULL;
time_t now = time(NULL);
bool replace_old;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
/* First, alloc and init a new struct for it */
co = (struct Cookie *)calloc(sizeof(struct Cookie), 1);
if(!co)
return NULL; /* bail out if we're this low on memory */
if(httpheader) {
/* This line was read off a HTTP-header */
char *sep;
what = malloc(MAX_COOKIE_LINE);
if(!what) {
free(co);
return NULL;
}
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 */
sep = strchr(ptr, '=');
if(sep && (!semiptr || (semiptr>sep)) ) {
/*
* There is a = sign and if there was a semicolon too, which make sure
* that the semicolon comes _after_ the equal sign.
*/
name[0]=what[0]=0; /* init the buffers */
if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%"
MAX_COOKIE_LINE_TXT "[^;\r\n]",
name, what)) {
/* this is a <name>=<what> pair */
char *whatptr;
/* Strip off trailing whitespace from the 'what' */
size_t len=strlen(what);
while(len && isspace((int)what[len-1])) {
what[len-1]=0;
len--;
}
/* Skip leading whitespace from the 'what' */
whatptr=what;
while(isspace((int)*whatptr)) {
whatptr++;
}
if(strequal("path", name)) {
co->path=strdup(whatptr);
if(!co->path) {
badcookie = TRUE; /* out of memory bad */
break;
}
}
else if(strequal("domain", name)) {
/* note that this name may or may not have a preceeding dot, but
we don't care about that, we treat the names the same anyway */
const char *domptr=whatptr;
int dotcount=1;
/* Count the dots, we need to make sure that there are enough
of them. */
if('.' == whatptr[0])
/* don't count the initial dot, assume it */
domptr++;
do {
domptr = strchr(domptr, '.');
if(domptr) {
domptr++;
dotcount++;
}
} while(domptr);
/* The original Netscape cookie spec defined that this domain name
MUST have three dots (or two if one of the seven holy TLDs),
but it seems that these kinds of cookies are in use "out there"
so we cannot be that strict. I've therefore lowered the check
to not allow less than two dots. */
if(dotcount < 2) {
/* Received and skipped a cookie with a domain using too few
dots. */
badcookie=TRUE; /* mark this as a bad cookie */
infof(data, "skipped cookie with illegal dotcount domain: %s\n",
whatptr);
}
else {
/* Now, we make sure that our host is within the given domain,
or the given domain is not valid and thus cannot be set. */
if('.' == whatptr[0])
whatptr++; /* ignore preceeding dot */
if(!domain || tailmatch(whatptr, domain)) {
const char *tailptr=whatptr;
if(tailptr[0] == '.')
tailptr++;
co->domain=strdup(tailptr); /* don't prefix w/dots
internally */
if(!co->domain) {
badcookie = TRUE;
break;
}
co->tailmatch=TRUE; /* we always do that if the domain name was
given */
}
else {
/* we did not get a tailmatch and then the attempted set domain
is not a domain to which the current host belongs. Mark as
bad. */
badcookie=TRUE;
infof(data, "skipped cookie with bad tailmatch domain: %s\n",
whatptr);
}
}
}
else if(strequal("version", name)) {
co->version=strdup(whatptr);
if(!co->version) {
badcookie = TRUE;
break;
}
}
else if(strequal("max-age", name)) {
/* Defined in RFC2109:
Optional. The Max-Age attribute defines the lifetime of the
cookie, in seconds. The delta-seconds value is a decimal non-
negative integer. After delta-seconds seconds elapse, the
client should discard the cookie. A value of zero means the
cookie should be discarded immediately.
*/
co->maxage = strdup(whatptr);
if(!co->maxage) {
badcookie = TRUE;
break;
}
co->expires =
atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now;
}
else if(strequal("expires", name)) {
co->expirestr=strdup(whatptr);
if(!co->expirestr) {
badcookie = TRUE;
break;
}
co->expires = curl_getdate(what, &now);
}
else if(!co->name) {
co->name = strdup(name);
co->value = strdup(whatptr);
if(!co->name || !co->value) {
badcookie = TRUE;
break;
}
}
/*
else this is the second (or more) name we don't know
about! */
}
else {
/* this is an "illegal" <what>=<this> pair */
}
}
else {
if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
what)) {
if(strequal("secure", what))
co->secure = TRUE;
/* else,
unsupported keyword without assign! */
}
}
if(!semiptr || !*semiptr) {
/* we already know there are no more cookies */
semiptr = NULL;
continue;
}
ptr=semiptr+1;
while(ptr && *ptr && isspace((int)*ptr))
ptr++;
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
if(!semiptr && *ptr)
/* There are no more semicolons, but there's a final name=value pair
coming up */
semiptr=strchr(ptr, '\0');
} while(semiptr);
if(!badcookie && !co->domain) {
if(domain) {
/* no domain was given in the header line, set the default */
co->domain=strdup(domain);
if(!co->domain)
badcookie = TRUE;
}
}
if(!badcookie && !co->path && path) {
/* no path was given in the header line, set the default */
char *endslash = strrchr(path, '/');
if(endslash) {
size_t pathlen = endslash-path+1; /* include the ending slash */
co->path=malloc(pathlen+1); /* one extra for the zero byte */
if(co->path) {
memcpy(co->path, path, pathlen);
co->path[pathlen]=0; /* zero terminate */
}
else
badcookie = TRUE;
}
}
free(what);
if(badcookie || !co->name) {
/* we didn't get a cookie name or a bad one,
this is an illegal line, bail out */
freecookie(co);
return NULL;
}
}
else {
/* This line is NOT a HTTP header style line, we do offer support for
reading the odd netscape cookies-file format here */
char *firstptr;
char *tok_buf;
int fields;
if(lineptr[0]=='#') {
/* don't even try the comments */
free(co);
return NULL;
}
/* strip off the possible end-of-line characters */
ptr=strchr(lineptr, '\r');
if(ptr)
*ptr=0; /* clear it */
ptr=strchr(lineptr, '\n');
if(ptr)
*ptr=0; /* clear it */
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
/* Here's a quick check to eliminate normal HTTP-headers from this */
if(!firstptr || strchr(firstptr, ':')) {
free(co);
return NULL;
}
/* Now loop through the fields and init the struct we already have
allocated */
for(ptr=firstptr, fields=0; ptr && !badcookie;
ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
switch(fields) {
case 0:
if(ptr[0]=='.') /* skip preceeding dots */
ptr++;
co->domain = strdup(ptr);
if(!co->domain)
badcookie = TRUE;
break;
case 1:
/* This field got its explanation on the 23rd of May 2001 by
Andrés García:
flag: A TRUE/FALSE value indicating if all machines within a given
domain can access the variable. This value is set automatically by
the browser, depending on the value you set for the domain.
As far as I can see, it is set to true when the cookie says
.domain.com and to false when the domain is complete www.domain.com
*/
co->tailmatch=(bool)strequal(ptr, "TRUE"); /* store information */
break;
case 2:
/* It turns out, that sometimes the file format allows the path
field to remain not filled in, we try to detect this and work
around it! Andrés García made us aware of this... */
if (strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
/* only if the path doesn't look like a boolean option! */
co->path = strdup(ptr);
if(!co->path)
badcookie = TRUE;
break;
}
/* this doesn't look like a path, make one up! */
co->path = strdup("/");
if(!co->path)
badcookie = TRUE;
fields++; /* add a field and fall down to secure */
/* FALLTHROUGH */
case 3:
co->secure = (bool)strequal(ptr, "TRUE");
break;
case 4:
co->expires = atoi(ptr);
break;
case 5:
co->name = strdup(ptr);
if(!co->name)
badcookie = TRUE;
break;
case 6:
co->value = strdup(ptr);
if(!co->value)
badcookie = TRUE;
break;
}
}
if(6 == fields) {
/* we got a cookie with blank contents, fix it */
co->value = strdup("");
if(!co->value)
badcookie = TRUE;
else
fields++;
}
if(!badcookie && (7 != fields))
/* we did not find the sufficient number of fields */
badcookie = TRUE;
if(badcookie) {
freecookie(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! */
freecookie(co);
return NULL;
}
co->livecookie = c->running;
/* now, we have parsed the incoming line, we must now check if this
superceeds an already existing cookie, which it may if the previous have
the same domain and path as this */
clist = c->cookies;
replace_old = FALSE;
while(clist) {
if(strequal(clist->name, co->name)) {
/* the names are identical */
if(clist->domain && co->domain) {
if(strequal(clist->domain, co->domain))
/* The domains are identical */
replace_old=TRUE;
}
else if(!clist->domain && !co->domain)
replace_old = TRUE;
if(replace_old) {
/* the domains were identical */
if(clist->path && co->path) {
if(strequal(clist->path, co->path)) {
replace_old = TRUE;
}
else
replace_old = FALSE;
}
else if(!clist->path && !co->path)
replace_old = TRUE;
else
replace_old = FALSE;
}
if(replace_old && !co->livecookie && clist->livecookie) {
/* Both cookies matched fine, except that the already present
cookie is "live", which means it was set from a header, while
the new one isn't "live" and thus only read from a file. We let
live cookies stay alive */
/* Free the newcomer and get out of here! */
freecookie(co);
return NULL;
}
if(replace_old) {
co->next = clist->next; /* get the next-pointer first */
/* then free all the old pointers */
if(clist->name)
free(clist->name);
if(clist->value)
free(clist->value);
if(clist->domain)
free(clist->domain);
if(clist->path)
free(clist->path);
if(clist->expirestr)
free(clist->expirestr);
if(clist->version)
free(clist->version);
if(clist->maxage)
free(clist->maxage);
*clist = *co; /* then store all the new data */
free(co); /* free the newly alloced memory */
co = clist; /* point to the previous struct instead */
/* We have replaced a cookie, now skip the rest of the list but
make sure the 'lastc' pointer is properly set */
do {
lastc = clist;
clist = clist->next;
} while(clist);
break;
}
}
lastc = clist;
clist = clist->next;
}
if(c->running)
/* Only show this when NOT reading the cookies from a file */
infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, expire %d\n",
replace_old?"Replaced":"Added", co->name, co->value,
co->domain, co->path, co->expires);
if(!replace_old) {
/* then make the last item point on this new one */
if(lastc)
lastc->next = co;
else
c->cookies = co;
}
c->numcookies++; /* one more cookie in the jar */
return co;
}
/*****************************************************************************
*
* Curl_cookie_init()
*
* 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(struct SessionHandle *data,
char *file,
struct CookieInfo *inc,
bool newsession)
{
struct CookieInfo *c;
FILE *fp;
bool fromfile=TRUE;
if(NULL == inc) {
/* we didn't get a struct, create one */
c = (struct CookieInfo *)calloc(1, sizeof(struct CookieInfo));
if(!c)
return NULL; /* failed to get memory */
c->filename = strdup(file?file:"none"); /* copy the name just in case */
}
else {
/* we got an already existing one, use that */
c = inc;
}
c->running = FALSE; /* this is not running, this is init */
if(file && strequal(file, "-")) {
fp = stdin;
fromfile=FALSE;
}
else
fp = file?fopen(file, "r"):NULL;
c->newsession = newsession; /* new session? */
if(fp) {
char *lineptr;
bool headerline;
char *line = (char *)malloc(MAX_COOKIE_LINE);
if(line) {
while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
headerline=TRUE;
}
else {
lineptr=line;
headerline=FALSE;
}
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
}
free(line); /* free the line buffer */
}
if(fromfile)
fclose(fp);
}
c->running = TRUE; /* now, we're running */
return c;
}
/*****************************************************************************
*
* Curl_cookie_getlist()
*
* For a given host and path, return a linked list of cookies that the
* client should send to the server if used now. The secure boolean informs
* the cookie if a secure connection is achieved or not.
*
* It shall only return cookies that haven't expired.
*
****************************************************************************/
struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
char *host, char *path, bool secure)
{
struct Cookie *newco;
struct Cookie *co;
time_t now = time(NULL);
struct Cookie *mainco=NULL;
if(!c || !c->cookies)
return NULL; /* no cookie struct or no cookies in the struct */
co = c->cookies;
while(co) {
/* only process this cookie if it is not expired or had no expire
date AND that if the cookie requires we're secure we must only
continue if we are! */
if( (co->expires<=0 || (co->expires> now)) &&
(co->secure?secure:TRUE) ) {
/* now check if the domain is correct */
if(!co->domain ||
(co->tailmatch && tailmatch(co->domain, host)) ||
(!co->tailmatch && strequal(host, co->domain)) ) {
/* the right part of the host matches the domain stuff in the
cookie data */
/* now check the left part of the path with the cookies path
requirement */
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 */
newco = (struct Cookie *)malloc(sizeof(struct Cookie));
if(newco) {
/* first, copy the whole source cookie: */
memcpy(newco, co, sizeof(struct Cookie));
/* then modify our next */
newco->next = mainco;
/* point the main to us */
mainco = newco;
}
else {
/* failure, clear up the allocated chain and return NULL */
while(mainco) {
co = mainco->next;
free(mainco);
mainco = co;
}
return NULL;
}
}
}
}
co = co->next;
}
return mainco; /* return the new list */
}
/*****************************************************************************
*
* Curl_cookie_freelist()
*
* Free a list of cookies previously returned by Curl_cookie_getlist();
*
****************************************************************************/
void Curl_cookie_freelist(struct Cookie *co)
{
struct Cookie *next;
if(co) {
while(co) {
next = co->next;
free(co); /* we only free the struct since the "members" are all
just copied! */
co = next;
}
}
}
/*****************************************************************************
*
* Curl_cookie_cleanup()
*
* Free a "cookie object" previous created with cookie_init().
*
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
struct Cookie *co;
struct Cookie *next;
if(c) {
if(c->filename)
free(c->filename);
co = c->cookies;
while(co) {
next = co->next;
freecookie(co);
co = next;
}
free(c); /* free the base struct as well */
}
}
/*
* Curl_cookie_output()
*
* Writes all internally known cookies to the specified file. Specify
* "-" as file name to write to stdout.
*
* The function returns non-zero on write failure.
*/
int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
{
struct Cookie *co;
FILE *out;
bool use_stdout=FALSE;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
destination file */
return 0;
if(strequal("-", dumphere)) {
/* use stdout */
out = stdout;
use_stdout=TRUE;
}
else {
out = fopen(dumphere, "w");
if(!out)
return 1; /* failure */
}
if(c) {
fputs("# Netscape HTTP Cookie File\n"
"# http://www.netscape.com/newsref/std/cookie_spec.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
co = c->cookies;
while(co) {
fprintf(out,
"%s%s\t" /* domain */
"%s\t" /* tailmatch */
"%s\t" /* path */
"%s\t" /* secure */
"%u\t" /* expires */
"%s\t" /* name */
"%s\n", /* value */
/* Make sure all domains are prefixed with a dot if they allow
tailmatching. This is Mozilla-style. */
(co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
co->domain?co->domain:"unknown",
co->tailmatch?"TRUE":"FALSE",
co->path?co->path:"/",
co->secure?"TRUE":"FALSE",
(unsigned int)co->expires,
co->name,
co->value?co->value:"");
co=co->next;
}
}
if(!use_stdout)
fclose(out);
return 0;
}
#endif /* CURL_DISABLE_HTTP */

95
Utilities/cmcurl/cookie.h Normal file
View File

@ -0,0 +1,95 @@
#ifndef __COOKIE_H
#define __COOKIE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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 <stdio.h>
#ifdef WIN32
#include <time.h>
#else
#include <sys/time.h>
#endif
#include <curl/curl.h>
struct Cookie {
struct Cookie *next; /* next in the chain */
char *name; /* <this> = value */
char *value; /* name = <this> */
char *path; /* path = <this> */
char *domain; /* domain = <this> */
long expires; /* expires = <this> */
char *expirestr; /* the plain text version */
bool tailmatch; /* weather we do tail-matchning of the domain name */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
};
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 */
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. RFC 2109
section 6.3 says:
"at least 4096 bytes per cookie (as measured by the size of the characters
that comprise the cookie non-terminal in the syntax description of the
Set-Cookie header)"
*/
#define MAX_COOKIE_LINE 5000
#define MAX_COOKIE_LINE_TXT "4999"
/* This is the maximum length of a cookie name we deal with: */
#define MAX_NAME 1024
#define MAX_NAME_TXT "1023"
struct SessionHandle;
/*
* Add a cookie to the internal list of cookies. The domain and path arguments
* are only used if the header boolean is TRUE.
*/
struct Cookie *Curl_cookie_add(struct SessionHandle *data,
struct CookieInfo *, bool header, char *line,
char *domain, char *path);
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
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 *);
int Curl_cookie_output(struct CookieInfo *, char *);
#endif

View File

@ -0,0 +1,25 @@
This package was cmakified by Andy Cedilnik <andy . cedilnik @ kitware.com>
It was downloaded from http://curl.haxx.se
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2004, Daniel Stenberg, <daniel@haxx.se>.
All rights reserved.
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright
notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

1340
Utilities/cmcurl/curl/curl.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
#ifndef __CURL_CURLVER_H
#define __CURL_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.12.1"
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal. All three numbers are always represented using two digits. 1.2
would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
This 6-digit hexadecimal number does not show pre-release number, and it is
always a greater number in a more recent release. It makes comparisons with
greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x70C01
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 12
#define LIBCURL_VERSION_PATCH 1
#endif /* __CURL_CURLVER_H */

View File

@ -0,0 +1,81 @@
#ifndef __CURL_EASY_H
#define __CURL_EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
CURL *curl_easy_init(void);
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURLcode curl_easy_perform(CURL *curl);
void curl_easy_cleanup(CURL *curl);
/*
* NAME curl_easy_getinfo()
*
* DESCRIPTION
*
* Request internal information from the curl session with this function. The
* third argument MUST be a pointer to a long, a pointer to a char * or a
* pointer to a double (as the documentation describes elsewhere). The data
* pointed to will be filled in accordingly and can be relied upon only if the
* function returns CURLE_OK. This function is intended to get used *AFTER* a
* performed transfer, all results from this function are undefined until the
* transfer is completed.
*/
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
/*
* NAME curl_easy_duphandle()
*
* DESCRIPTION
*
* Creates a new curl session handle with the same options set for the handle
* passed in. Duplicating a handle could only be a matter of cloning data and
* options, internal state info and things like persistant connections cannot
* be transfered. It is useful in multithreaded applications when you can run
* curl_easy_duphandle() for each new thread to avoid a series of identical
* curl_easy_setopt() invokes in every thread.
*/
CURL* curl_easy_duphandle(CURL *curl);
/*
* NAME curl_easy_reset()
*
* DESCRIPTION
*
* Re-initializes a CURL handle to the default values. This puts back the
* handle to the same state as it was in when it was just created.
*
* It does keep: live connections, the Session ID cache, the DNS cache and the
* cookies.
*/
void curl_easy_reset(CURL *curl);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,54 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef H_MPRINTF
#define H_MPRINTF
#include <stdarg.h>
#include <stdio.h> /* needed for FILE */
int curl_mprintf(const char *format, ...);
int curl_mfprintf(FILE *fd, const char *format, ...);
int curl_msprintf(char *buffer, const char *format, ...);
int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...);
int curl_mvprintf(const char *format, va_list args);
int curl_mvfprintf(FILE *fd, const char *format, va_list args);
int curl_mvsprintf(char *buffer, const char *format, va_list args);
int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, va_list args);
char *curl_maprintf(const char *format, ...);
char *curl_mvaprintf(const char *format, va_list args);
#ifdef _MPRINTF_REPLACE
# define printf curl_mprintf
# define fprintf curl_mfprintf
# define sprintf curl_msprintf
# define snprintf curl_msnprintf
# define vprintf curl_mvprintf
# define vfprintf curl_mvfprintf
# define vsprintf curl_mvsprintf
# define vsnprintf curl_mvsnprintf
# define aprintf curl_maprintf
# define vaprintf curl_mvaprintf
#endif
#endif /* H_MPRINTF */

View File

@ -0,0 +1,221 @@
#ifndef __CURL_MULTI_H
#define __CURL_MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/*
This is meant to be the "external" header file. Don't give away any
internals here!
This document presents a mixture of ideas from at least:
- Daniel Stenberg
- Steve Dekorte
- Sterling Hughes
- Ben Greear
-------------------------------------------
GOALS
o Enable a "pull" interface. The application that uses libcurl decides where
and when to ask libcurl to get/send data.
o Enable multiple simultaneous transfers in the same thread without making it
complicated for the application.
o Enable the application to select() on its own file descriptors and curl's
file descriptors simultaneous easily.
*/
#if defined(_WIN32) && !defined(WIN32)
/* Chris Lewis mentioned that he doesn't get WIN32 defined, only _WIN32 so we
make this adjustment to catch this. */
#define WIN32 1
#endif
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock2.h>
#else
/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
libc5-based Linux systems. Only include it on system that are known to
require it! */
#if defined(_AIX) || defined(NETWARE)
#include <sys/select.h>
#endif
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#endif
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void CURLM;
typedef enum {
CURLM_CALL_MULTI_PERFORM=-1, /* please call curl_multi_perform() soon */
CURLM_OK,
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
CURLM_LAST
} CURLMcode;
typedef enum {
CURLMSG_NONE, /* first, not used */
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
the CURLcode of the transfer */
CURLMSG_LAST /* last, not used */
} CURLMSG;
struct CURLMsg {
CURLMSG msg; /* what this message means */
CURL *easy_handle; /* the handle it concerns */
union {
void *whatever; /* message-specific data */
CURLcode result; /* return code for transfer */
} data;
};
typedef struct CURLMsg CURLMsg;
/*
* Name: curl_multi_init()
*
* Desc: inititalize multi-style curl usage
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/
CURLM *curl_multi_init(void);
/*
* Name: curl_multi_add_handle()
*
* Desc: add a standard curl handle to the multi stack
* Returns: CURLMcode type, general multi error code.
*/
CURLMcode curl_multi_add_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_remove_handle()
*
* Desc: removes a curl handle from the multi stack again
* Returns: CURLMcode type, general multi error code.
*/
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_fdset()
*
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
* poll() on. We want curl_multi_perform() called as soon as one of
* them are ready.
* Returns: CURLMcode type, general multi error code.
*/
CURLMcode curl_multi_fdset(CURLM *multi_handle,
fd_set *read_fd_set,
fd_set *write_fd_set,
fd_set *exc_fd_set,
int *max_fd);
/*
* Name: curl_multi_perform()
*
* Desc: When the app thinks there's data available for curl it calls this
* function to read/write whatever there is right now. This returns
* as soon as the reads and writes are done. This function does not
* require that there actually is data available for reading or that
* data can be written, it can be called just in case. It returns
* the number of handles that still transfer data in the second
* argument's integer-pointer.
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
* still have occurred problems on invidual transfers even when this
* returns OK.
*/
CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
/*
* Name: curl_multi_cleanup()
*
* Desc: Cleans up and removes a whole multi stack. It does not free or
* touch any individual easy handles in any way. We need to define
* in what state those handles will be if this function is called
* in the middle of a transfer.
* Returns: CURLMcode type, general multi error code.
*/
CURLMcode curl_multi_cleanup(CURLM *multi_handle);
/*
* Name: curl_multi_info_read()
*
* Desc: Ask the multi handle if there's any messages/informationals from
* the individual transfers. Messages include informationals such as
* error code from the transfer or just the fact that a transfer is
* completed. More details on these should be written down as well.
*
* Repeated calls to this function will return a new struct each
* time, until a special "end of msgs" struct is returned as a signal
* that there is no more to get at this point.
*
* The data the returned pointer points to will not survive calling
* curl_multi_cleanup().
*
* The 'CURLMsg' struct is meant to be very simple and only contain
* very basic informations. If more involved information is wanted,
* we will provide the particular "transfer handle" in that struct
* and that should/could/would be used in subsequent
* curl_easy_getinfo() calls (or similar). The point being that we
* must never expose complex structs to applications, as then we'll
* undoubtably get backwards compatibility problems in the future.
*
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
* of structs. It also writes the number of messages left in the
* queue (after this read) in the integer the second argument points
* to.
*/
CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue);
/*
* NAME curl_multi_strerror()
*
* DESCRIPTION
*
* The curl_multi_strerror function may be used to turn a CURLMcode value
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
const char *curl_multi_strerror(CURLMcode);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif

View File

@ -0,0 +1,34 @@
#ifndef __STDC_HEADERS_H
#define __STDC_HEADERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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 <sys/types.h>
size_t fread (void *, size_t, size_t, FILE *);
size_t fwrite (const void *, size_t, size_t, FILE *);
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
#endif

View File

@ -0,0 +1 @@
/* not used */

View File

@ -0,0 +1,50 @@
#ifndef _CURL_MEMORY_H
#define _CURL_MEMORY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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 <curl/curl.h> /* for the typedefs */
extern curl_malloc_callback Curl_cmalloc;
extern curl_free_callback Curl_cfree;
extern curl_realloc_callback Curl_crealloc;
extern curl_strdup_callback Curl_cstrdup;
extern curl_calloc_callback Curl_ccalloc;
#ifndef CURLDEBUG
/* Only do this define-mania if we're not using the memdebug system, as that
has preference on this magic. */
#undef strdup
#define strdup(ptr) Curl_cstrdup(ptr)
#undef malloc
#define malloc(size) Curl_cmalloc(size)
#undef calloc
#define calloc(nbelem,size) Curl_ccalloc(nbelem, size)
#undef realloc
#define realloc(ptr,size) Curl_crealloc(ptr, size)
#undef free
#define free(ptr) Curl_cfree(ptr)
#endif
#endif /* _CURL_MEMORY_H */

95
Utilities/cmcurl/curlx.h Normal file
View File

@ -0,0 +1,95 @@
#ifndef __CURLX_H
#define __CURLX_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/*
* Defines protos and includes all header files that provide the curlx_*
* functions. The curlx_* functions are not part of the libcurl API, but are
* stand-alone functions whose sources can be built and linked by apps if need
* be.
*/
#include <curl/mprintf.h>
/* this is still a public header file that provides the curl_mprintf()
functions while they still are offered publicly. They will be made library-
private one day */
#include "strequal.h"
/* "strequal.h" provides the strequal protos */
#include "strtoofft.h"
/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a
curl_off_t number from a given string.
*/
#include "timeval.h"
/*
"timeval.h" sets up a 'struct timeval' even for platforms that otherwise
don't have one and has protos for these functions:
curlx_tvnow()
curlx_tvdiff()
curlx_tvdiff_secs()
*/
/* Now setup curlx_ * names for the functions that are to become curlx_ and
be removed from a future libcurl official API:
curlx_getenv
curlx_mprintf (and its variations)
curlx_strequal
curlx_strnequal
*/
#define curlx_getenv curl_getenv
#define curlx_strequal curl_strequal
#define curlx_strnequal curl_strnequal
#define curlx_mvsnprintf curl_mvsnprintf
#define curlx_msnprintf curl_msnprintf
#define curlx_maprintf curl_maprintf
#define curlx_mvaprintf curl_mvaprintf
#define curlx_msprintf curl_msprintf
#define curlx_mprintf curl_mprintf
#define curlx_mfprintf curl_mfprintf
#define curlx_mvsprintf curl_mvsprintf
#define curlx_mvprintf curl_mvprintf
#define curlx_mvfprintf curl_mvfprintf
#ifdef ENABLE_CURLX_PRINTF
/* If this define is set, we define all "standard" printf() functions to use
the curlx_* version instead. It makes the source code transparant and
easier to understand/patch. */
# define printf curlx_mprintf
# define fprintf curlx_mfprintf
# define sprintf curlx_msprintf
# define snprintf curlx_msnprintf
# define vprintf curlx_mvprintf
# define vfprintf curlx_mvfprintf
# define vsprintf curlx_mvsprintf
# define vsnprintf curlx_mvsnprintf
# define aprintf curlx_maprintf
# define vaprintf curlx_mvaprintf
#endif /* ENABLE_CURLX_PRINTF */
#endif /* __CURLX_H */

221
Utilities/cmcurl/dict.c Normal file
View File

@ -0,0 +1,221 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <netdb.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#endif
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#include "progress.h"
#include "strequal.h"
#include "dict.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
CURLcode Curl_dict(struct connectdata *conn)
{
char *word;
char *ppath;
char *database = NULL;
char *strategy = NULL;
char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */
CURLcode result;
struct SessionHandle *data=conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = conn->path;
curl_off_t *bytecount = &conn->bytecount;
if(conn->bits.user_passwd) {
/* AUTH is missing */
}
if (strnequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
strnequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
strnequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
word = strchr(path, ':');
if (word) {
word++;
database = strchr(word, ':');
if (database) {
*database++ = (char)0;
strategy = strchr(database, ':');
if (strategy) {
*strategy++ = (char)0;
nthdef = strchr(strategy, ':');
if (nthdef) {
*nthdef++ = (char)0;
}
}
}
}
if ((word == NULL) || (*word == (char)0)) {
failf(data, "lookup word is missing");
}
if ((database == NULL) || (*database == (char)0)) {
database = (char *)"!";
}
if ((strategy == NULL) || (*strategy == (char)0)) {
strategy = (char *)".";
}
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH "
"%s " /* database */
"%s " /* strategy */
"%s\n" /* word */
"QUIT\n",
database,
strategy,
word
);
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
return result;
}
else if (strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
strnequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
word = strchr(path, ':');
if (word) {
word++;
database = strchr(word, ':');
if (database) {
*database++ = (char)0;
nthdef = strchr(database, ':');
if (nthdef) {
*nthdef++ = (char)0;
}
}
}
if ((word == NULL) || (*word == (char)0)) {
failf(data, "lookup word is missing");
}
if ((database == NULL) || (*database == (char)0)) {
database = (char *)"!";
}
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE "
"%s " /* database */
"%s\n" /* word */
"QUIT\n",
database,
word);
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
return result;
}
else {
ppath = strchr(path, '/');
if (ppath) {
int i;
ppath++;
for (i = 0; ppath[i]; i++) {
if (ppath[i] == ':')
ppath[i] = ' ';
}
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"%s\n"
"QUIT\n", ppath);
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL);
if(result)
return result;
}
}
(void)nthdef;
return CURLE_OK;
}

30
Utilities/cmcurl/dict.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __DICT_H
#define __DICT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef CURL_DISABLE_DICT
CURLcode Curl_dict(struct connectdata *conn);
CURLcode Curl_dict_done(struct connectdata *conn);
#endif
#endif

583
Utilities/cmcurl/easy.c Normal file
View File

@ -0,0 +1,583 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "strequal.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <netdb.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#endif /* WIN32 ... */
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
#include "ssluse.h"
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
#include "share.h"
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
of win32_init() */
static void win32_cleanup(void)
{
WSACleanup();
}
/* win32_init() performs win32 socket initialization to properly setup the
stack to allow networking */
static CURLcode win32_init(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
#ifdef ENABLE_IPV6
wVersionRequested = MAKEWORD(2, 0);
#else
wVersionRequested = MAKEWORD(1, 1);
#endif
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return CURLE_FAILED_INIT;
/* Confirm that the Windows Sockets DLL supports what we need.*/
/* Note that if the DLL supports versions greater */
/* than wVersionRequested, it will still return */
/* wVersionRequested in wVersion. wHighVersion contains the */
/* highest supported version. */
if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return CURLE_FAILED_INIT;
}
/* The Windows Sockets DLL is acceptable. Proceed. */
return CURLE_OK;
}
#else
/* These functions exist merely to prevent compiler warnings */
static CURLcode win32_init(void) { return CURLE_OK; }
static void win32_cleanup(void) { }
#endif
#ifdef USE_LIBIDN
/*
* Initialise use of IDNA library.
* It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
* idna_to_ascii_lz().
*/
static void idna_init (void)
{
#ifdef WIN32
char buf[60];
UINT cp = GetACP();
if (!getenv("CHARSET") && cp > 0) {
snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
putenv(buf);
}
#else
/* to do? */
#endif
}
#endif /* USE_LIBIDN */
/* true globals -- for curl_global_init() and curl_global_cleanup() */
static unsigned int initialized = 0;
static long init_flags = 0;
/*
* If a memory-using function (like curl_getenv) is used before
* curl_global_init() is called, we need to have these pointers set already.
*/
curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
/**
* curl_global_init() globally initializes cURL given a bitwise set of the
* different features of what to initialize.
*/
CURLcode curl_global_init(long flags)
{
if (initialized)
return CURLE_OK;
/* Setup the default memory functions here (again) */
Curl_cmalloc = (curl_malloc_callback)malloc;
Curl_cfree = (curl_free_callback)free;
Curl_crealloc = (curl_realloc_callback)realloc;
Curl_cstrdup = (curl_strdup_callback)strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
if (flags & CURL_GLOBAL_SSL)
Curl_SSL_init();
if (flags & CURL_GLOBAL_WIN32)
if (win32_init() != CURLE_OK)
return CURLE_FAILED_INIT;
#ifdef _AMIGASF
if(!amiga_init())
return CURLE_FAILED_INIT;
#endif
#ifdef USE_LIBIDN
idna_init();
#endif
initialized = 1;
init_flags = flags;
return CURLE_OK;
}
/*
* curl_global_init_mem() globally initializes cURL and also registers the
* user provided callback routines.
*/
CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
curl_free_callback f, curl_realloc_callback r,
curl_strdup_callback s, curl_calloc_callback c)
{
CURLcode code;
/* Invalid input, return immediately */
if (!m || !f || !r || !s || !c)
return CURLE_FAILED_INIT;
/* Already initialized, don't do it again */
if ( initialized )
return CURLE_OK;
/* Call the actual init function first */
code = curl_global_init(flags);
if (code == CURLE_OK) {
Curl_cmalloc = m;
Curl_cfree = f;
Curl_cstrdup = s;
Curl_crealloc = r;
Curl_ccalloc = c;
}
return code;
}
/**
* curl_global_cleanup() globally cleanups cURL, uses the value of
* "init_flags" to determine what needs to be cleaned up and what doesn't.
*/
void curl_global_cleanup(void)
{
if (!initialized)
return;
Curl_global_host_cache_dtor();
if (init_flags & CURL_GLOBAL_SSL)
Curl_SSL_cleanup();
if (init_flags & CURL_GLOBAL_WIN32)
win32_cleanup();
#ifdef _AMIGASF
amiga_cleanup();
#endif
initialized = 0;
init_flags = 0;
}
/*
* curl_easy_init() is the external interface to alloc, setup and init an
* easy handle that is returned. If anything goes wrong, NULL is returned.
*/
CURL *curl_easy_init(void)
{
CURLcode res;
struct SessionHandle *data;
/* Make sure we inited the global SSL stuff */
if (!initialized) {
res = curl_global_init(CURL_GLOBAL_DEFAULT);
if(res)
/* something in the global init failed, return nothing */
return NULL;
}
/* We use curl_open() with undefined URL so far */
res = Curl_open(&data);
if(res != CURLE_OK)
return NULL;
return data;
}
/*
* curl_easy_setopt() is the external interface for setting options on an
* easy handle.
*/
typedef int (*func_T)(void);
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
{
va_list arg;
func_T param_func;
long param_long;
void *param_obj;
curl_off_t param_offset;
struct SessionHandle *data = curl;
CURLcode ret;
if(!curl)
return CURLE_BAD_FUNCTION_ARGUMENT;
va_start(arg, tag);
/* PORTING NOTE:
Object pointers can't necessarily be casted to function pointers and
therefore we need to know what type it is and read the correct type
at once. This should also correct problems with different sizes of
the types.
*/
if(tag < CURLOPTTYPE_OBJECTPOINT) {
/* This is a LONG type */
param_long = va_arg(arg, long);
ret = Curl_setopt(data, tag, param_long);
}
else if(tag < CURLOPTTYPE_FUNCTIONPOINT) {
/* This is a object pointer type */
param_obj = va_arg(arg, void *);
ret = Curl_setopt(data, tag, param_obj);
}
else if(tag < CURLOPTTYPE_OFF_T) {
/* This is a function pointer type */
param_func = va_arg(arg, func_T );
ret = Curl_setopt(data, tag, param_func);
}
else {
/* This is a curl_off_t type */
param_offset = va_arg(arg, curl_off_t);
ret = Curl_setopt(data, tag, param_offset);
}
va_end(arg);
return ret;
}
/*
* curl_easy_perform() is the external interface that performs a transfer
* previously setup.
*/
CURLcode curl_easy_perform(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
if ( ! (data->share && data->share->hostcache) ) {
if (Curl_global_host_cache_use(data) &&
data->hostcache != Curl_global_host_cache_get()) {
if (data->hostcache)
Curl_hash_destroy(data->hostcache);
data->hostcache = Curl_global_host_cache_get();
}
if (!data->hostcache) {
data->hostcache = Curl_mk_dnscache();
if(!data->hostcache)
/* While we possibly could survive and do good without a host cache,
the fact that creating it failed indicates that things are truly
screwed up and we should bail out! */
return CURLE_OUT_OF_MEMORY;
}
}
return Curl_perform(data);
}
/*
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
* easy handle.
*/
void curl_easy_cleanup(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
if(!data)
return;
if ( ! (data->share && data->share->hostcache) ) {
if ( !Curl_global_host_cache_use(data)) {
Curl_hash_destroy(data->hostcache);
}
}
Curl_close(data);
}
/*
* curl_easy_getinfo() is an external interface that allows an app to retrieve
* information from a performed transfer and similar.
*/
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
{
va_list arg;
void *paramp;
struct SessionHandle *data = (struct SessionHandle *)curl;
va_start(arg, info);
paramp = va_arg(arg, void *);
return Curl_getinfo(data, info, paramp);
}
/*
* curl_easy_duphandle() is an external interface to allow duplication of a
* given input easy handle. The returned handle will be a new working handle
* with all options set exactly as the input source handle.
*/
CURL *curl_easy_duphandle(CURL *incurl)
{
bool fail = TRUE;
struct SessionHandle *data=(struct SessionHandle *)incurl;
struct SessionHandle *outcurl = (struct SessionHandle *)
calloc(sizeof(struct SessionHandle), 1);
if(NULL == outcurl)
return NULL; /* failure */
do {
/*
* We setup a few buffers we need. We should probably make them
* get setup on-demand in the code, as that would probably decrease
* the likeliness of us forgetting to init a buffer here in the future.
*/
outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
if(!outcurl->state.headerbuff) {
break;
}
outcurl->state.headersize=HEADERSIZE;
/* copy all userdefined values */
outcurl->set = data->set;
outcurl->state.numconnects = data->state.numconnects;
outcurl->state.connects = (struct connectdata **)
malloc(sizeof(struct connectdata *) * outcurl->state.numconnects);
if(!outcurl->state.connects) {
break;
}
memset(outcurl->state.connects, 0,
sizeof(struct connectdata *)*outcurl->state.numconnects);
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
#ifndef CURL_DISABLE_HTTP
if(data->cookies) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
outcurl->cookies = Curl_cookie_init(data,
data->cookies->filename,
outcurl->cookies,
data->set.cookiesession);
if(!outcurl->cookies) {
break;
}
}
#endif /* CURL_DISABLE_HTTP */
/* duplicate all values in 'change' */
if(data->change.url) {
outcurl->change.url = strdup(data->change.url);
if(!outcurl->change.url)
break;
outcurl->change.url_alloc = TRUE;
}
if(data->change.proxy) {
outcurl->change.proxy = strdup(data->change.proxy);
if(!outcurl->change.proxy)
break;
outcurl->change.proxy_alloc = TRUE;
}
if(data->change.referer) {
outcurl->change.referer = strdup(data->change.referer);
if(!outcurl->change.referer)
break;
outcurl->change.referer_alloc = TRUE;
}
#ifdef USE_ARES
/* If we use ares, we setup a new ares channel for the new handle */
if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
break;
#endif
fail = FALSE; /* we reach this point and thus we are OK */
} while(0);
if(fail) {
if(outcurl) {
if(outcurl->state.connects)
free(outcurl->state.connects);
if(outcurl->state.headerbuff)
free(outcurl->state.headerbuff);
if(outcurl->change.proxy)
free(outcurl->change.proxy);
if(outcurl->change.url)
free(outcurl->change.url);
if(outcurl->change.referer)
free(outcurl->change.referer);
free(outcurl); /* free the memory again */
outcurl = NULL;
}
}
return outcurl;
}
/*
* curl_easy_reset() is an external interface that allows an app to re-
* initialize a session handle to the default values.
*/
void curl_easy_reset(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
/* zero out UserDefined data: */
memset(&data->set, 0, sizeof(struct UserDefined));
/* zero out Progress data: */
memset(&data->progress, 0, sizeof(struct Progress));
/* The remainder of these calls have been taken from Curl_open() */
data->set.out = stdout; /* default output to stdout */
data->set.in = stdin; /* default input from stdin */
data->set.err = stderr; /* default stderr to stderr */
/* use fwrite as default function to store output */
data->set.fwrite = (curl_write_callback)fwrite;
/* use fread as default function to read input */
data->set.fread = (curl_read_callback)fread;
data->set.infilesize = -1; /* we don't know any size */
data->state.current_speed = -1; /* init to negative == impossible */
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
data->set.ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
/* make libcurl quiet by default: */
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
/* 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 */
data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic */
data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
/*
* libcurl 7.10 introduced 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
}

135
Utilities/cmcurl/escape.c Normal file
View File

@ -0,0 +1,135 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
#include "setup.h"
#include <ctype.h>
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
char *curl_escape(const char *string, int inlength)
{
size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
char *ns;
char *testing_ptr;
unsigned char in;
size_t newlen = alloc;
int strindex=0;
size_t length;
ns = malloc(alloc);
if(!ns)
return NULL;
length = alloc-1;
while(length--) {
in = *string;
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) {
alloc *= 2;
testing_ptr = realloc(ns, alloc);
if(!testing_ptr) {
free( ns );
return NULL;
}
else {
ns = testing_ptr;
}
}
snprintf(&ns[strindex], 4, "%%%02X", in);
strindex+=3;
}
else {
/* just copy this */
ns[strindex++]=in;
}
string++;
}
ns[strindex]=0; /* terminate it */
return ns;
}
#define ishex(in) ((in >= 'a' && in <= 'f') || \
(in >= 'A' && in <= 'F') || \
(in >= '0' && in <= '9'))
char *curl_unescape(const char *string, int length)
{
int alloc = (length?length:(int)strlen(string))+1;
char *ns = malloc(alloc);
unsigned char in;
int strindex=0;
long hex;
if( !ns )
return NULL;
while(--alloc > 0) {
in = *string;
if(('%' == in) && ishex(string[1]) && ishex(string[2])) {
/* this is two hexadecimal digits following a '%' */
char hexstr[3];
char *ptr;
hexstr[0] = string[1];
hexstr[1] = string[2];
hexstr[2] = 0;
hex = strtol(hexstr, &ptr, 16);
in = (unsigned char)hex; /* this long is never bigger than 255 anyway */
string+=2;
alloc-=2;
}
ns[strindex++] = in;
string++;
}
ns[strindex]=0; /* terminate it */
return ns;
}
/* For operating systems/environments that use different malloc/free
ssystems for the app and for this library, we provide a free that uses
the library's memory system */
void curl_free(void *p)
{
if(p)
free(p);
}

32
Utilities/cmcurl/escape.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef __ESCAPE_H
#define __ESCAPE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
char *curl_escape(const char *string, int length);
char *curl_unescape(const char *string, int length);
#endif

390
Utilities/cmcurl/file.c Normal file
View File

@ -0,0 +1,390 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#ifndef CURL_DISABLE_FILE
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <time.h>
#include <io.h>
#include <fcntl.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <sys/time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#endif
#include "urldata.h"
#include <curl/curl.h>
#include "progress.h"
#include "sendf.h"
#include "escape.h"
#include "file.h"
#include "speedcheck.h"
#include "getinfo.h"
#include "transfer.h"
#include "url.h"
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
/*
* Curl_file_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. We emulate a
* connect-then-transfer protocol and "connect" to the file here
*/
CURLcode Curl_file_connect(struct connectdata *conn)
{
char *real_path = curl_unescape(conn->path, 0);
struct FILEPROTO *file;
int fd;
#if defined(WIN32) || defined(__EMX__)
int i;
char *actual_path;
#endif
if(!real_path)
return CURLE_OUT_OF_MEMORY;
file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1);
if(!file) {
free(real_path);
return CURLE_OUT_OF_MEMORY;
}
conn->proto.file = file;
#if defined(WIN32) || defined(__EMX__)
/* If the first character is a slash, and there's
something that looks like a drive at the beginning of
the path, skip the slash. If we remove the initial
slash in all cases, paths without drive letters end up
relative to the current directory which isn't how
browsers work.
Some browsers accept | instead of : as the drive letter
separator, so we do too.
On other platforms, we need the slash to indicate an
absolute pathname. On Windows, absolute paths start
with a drive letter.
*/
actual_path = real_path;
if ((actual_path[0] == '/') &&
actual_path[1] &&
(actual_path[2] == ':' || actual_path[2] == '|'))
{
actual_path[2] = ':';
actual_path++;
}
/* change path separators from '/' to '\\' for Windows and OS/2 */
for (i=0; actual_path[i] != '\0'; ++i)
if (actual_path[i] == '/')
actual_path[i] = '\\';
fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */
file->path = actual_path;
#else
fd = open(real_path, O_RDONLY);
file->path = real_path;
#endif
file->freepath = real_path; /* free this when done */
if(!conn->data->set.upload && (fd == -1)) {
failf(conn->data, "Couldn't open file %s", conn->path);
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE);
return CURLE_FILE_COULDNT_READ_FILE;
}
file->fd = fd;
return CURLE_OK;
}
#if defined(WIN32) && (SIZEOF_CURL_OFF_T > 4)
#define lseek(x,y,z) _lseeki64(x, y, z)
#endif
CURLcode Curl_file_done(struct connectdata *conn,
CURLcode status)
{
struct FILEPROTO *file = conn->proto.file;
(void)status; /* not used */
Curl_safefree(file->freepath);
return CURLE_OK;
}
#if defined(WIN32) || defined(__EMX__)
#define DIRSEP '\\'
#else
#define DIRSEP '/'
#endif
static CURLcode file_upload(struct connectdata *conn)
{
struct FILEPROTO *file = conn->proto.file;
char *dir = strchr(file->path, DIRSEP);
FILE *fp;
CURLcode res=CURLE_OK;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
size_t nread;
size_t nwrite;
curl_off_t bytecount = 0;
struct timeval now = Curl_tvnow();
/*
* Since FILE: doesn't do the full init, we need to provide some extra
* assignments here.
*/
conn->fread = data->set.fread;
conn->fread_in = data->set.in;
conn->upload_fromhere = buf;
if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
if(!dir[1])
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
fp = fopen(file->path, "wb");
if(!fp) {
failf(data, "Can't open %s for writing", file->path);
return CURLE_WRITE_ERROR;
}
if(-1 != data->set.infilesize)
/* known size of data to "upload" */
Curl_pgrsSetUploadSize(data, data->set.infilesize);
while (res == CURLE_OK) {
int readcount;
res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
if(res)
return res;
nread = (size_t)readcount;
if (nread <= 0)
break;
/* write the data to the target */
nwrite = fwrite(buf, 1, nread, fp);
if(nwrite != nread) {
res = CURLE_SEND_ERROR;
break;
}
bytecount += nread;
Curl_pgrsSetUploadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
else
res = Curl_speedcheck(data, now);
}
if(!res && Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
fclose(fp);
return res;
}
/*
* Curl_file() is the protocol-specific function for the do-phase, separated
* from the connect-phase above. Other protocols merely setup the transfer in
* the do-phase, to have it done in the main transfer loop but since some
* platforms we support don't allow select()ing etc on file handles (as
* opposed to sockets) we instead perform the whole do-operation in this
* function.
*/
CURLcode Curl_file(struct connectdata *conn)
{
/* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system)
are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
CURLcode res = CURLE_OK;
struct stat statbuf;
curl_off_t expected_size=0;
bool fstated=FALSE;
ssize_t nread;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
int fd;
struct timeval now = Curl_tvnow();
Curl_readwrite_init(conn);
Curl_initinfo(data);
Curl_pgrsStartNow(data);
if(data->set.upload)
return file_upload(conn);
/* get the fd from the connection phase */
fd = conn->proto.file->fd;
/* 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;
fstated = TRUE;
}
/* If we have selected NOBODY and HEADER, it means that we only want file
information. Which for FILE can't be much more than the file size and
date. */
if(conn->bits.no_body && data->set.include_header && fstated) {
CURLcode result;
snprintf(buf, sizeof(data->state.buffer),
"Content-Length: %" FORMAT_OFF_T "\r\n", expected_size);
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
if(result)
return result;
result = Curl_client_write(data, CLIENTWRITE_BOTH,
(char *)"Accept-ranges: bytes\r\n", 0);
if(result)
return result;
#ifdef HAVE_STRFTIME
if(fstated) {
struct tm *tm;
time_t cuClock = (time_t)statbuf.st_mtime;
#ifdef HAVE_GMTIME_R
struct tm buffer;
tm = (struct tm *)gmtime_r(&cuClock, &buffer);
#else
tm = gmtime(&cuClock);
#endif
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S GMT\r\n",
tm);
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
}
#endif
return result;
}
/* 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 (fstated && (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
in Winsock */
if(fstated)
Curl_pgrsSetDownloadSize(data, expected_size);
if(conn->resume_from)
lseek(fd, conn->resume_from, SEEK_SET);
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
while (res == CURLE_OK) {
nread = read(fd, buf, BUFSIZE-1);
if ( nread > 0)
buf[nread] = 0;
if (nread <= 0)
break;
bytecount += nread;
res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
if(res)
return res;
Curl_pgrsSetDownloadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
else
res = Curl_speedcheck(data, now);
}
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
close(fd);
return res;
}
#endif

31
Utilities/cmcurl/file.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef __FILE_H
#define __FILE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef CURL_DISABLE_FILE
CURLcode Curl_file(struct connectdata *);
CURLcode Curl_file_done(struct connectdata *, CURLcode);
CURLcode Curl_file_connect(struct connectdata *);
#endif
#endif

1484
Utilities/cmcurl/formdata.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
#ifndef __FORMDATA_H
#define __FORMDATA_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
enum formtype {
FORM_DATA, /* regular data */
FORM_FILE /* 'line' points to a file name we should read from */
};
/* plain and simple linked list with lines to send */
struct FormData {
struct FormData *next;
enum formtype type;
char *line;
size_t length;
};
struct Form {
struct FormData *data; /* current form line to send */
size_t sent; /* number of bytes of the current line that has
already been sent in a previous invoke */
FILE *fp; /* file to read from */
};
/* used by FormAdd for temporary storage */
typedef struct FormInfo {
char *name;
bool name_alloc;
size_t namelength;
char *value;
bool value_alloc;
size_t contentslength;
char *contenttype;
bool contenttype_alloc;
long flags;
char *buffer; /* pointer to existing buffer used for file upload */
size_t bufferlength;
char *showfilename; /* The file name to show. If not set, the actual
file name will be used */
bool showfilename_alloc;
struct curl_slist* contentheader;
struct FormInfo *more;
} FormInfo;
int Curl_FormInit(struct Form *form, struct FormData *formdata );
CURLcode
Curl_getFormData(struct FormData **,
struct curl_httppost *post,
curl_off_t *size);
/* fread() emulation */
size_t Curl_FormReader(char *buffer,
size_t size,
size_t nitems,
FILE *mydata);
/*
* Curl_formpostheader() returns the first line of the formpost, the
* request-header part (which is not part of the request-body like the rest of
* the post).
*/
char *Curl_formpostheader(void *formp, size_t *len);
char *Curl_FormBoundary(void);
void Curl_formclean(struct FormData *);
#endif

2774
Utilities/cmcurl/ftp.c Normal file

File diff suppressed because it is too large Load Diff

37
Utilities/cmcurl/ftp.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef __FTP_H
#define __FTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef CURL_DISABLE_FTP
CURLcode Curl_ftp(struct connectdata *conn);
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode);
CURLcode Curl_ftp_connect(struct connectdata *conn);
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
int *ftpcode);
CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
#endif
#endif

2471
Utilities/cmcurl/getdate.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
/*
** Originally written by Steven M. Bellovin <smb@research.att.com> while
** at the University of North Carolina at Chapel Hill. Later tweaked by
** a couple of people on Usenet. Completely overhauled by Rich $alz
** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
**
** This code is in the public domain and has no copyright.
*/
# include "setup.h"
#ifndef PARAMS
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
# define PARAMS(Args) Args
# else
# define PARAMS(Args) ()
# endif
#endif
#ifdef vms
# include <types.h>
# include <time.h>
#else
# include <sys/types.h>
# if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
# else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
# endif
#endif /* defined (vms) */
time_t curl_getdate PARAMS ((const char *p, const time_t *now));

70
Utilities/cmcurl/getenv.c Normal file
View File

@ -0,0 +1,70 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#endif
#ifdef VMS
#include <unixlib.h>
#endif
#include <curl/curl.h>
#include "curl_memory.h"
#include "memdebug.h"
static
char *GetEnv(const char *variable)
{
#ifdef WIN32
/* This shit requires windows.h (HUGE) to be included */
char env[MAX_PATH]; /* MAX_PATH is from windef.h */
char *temp = getenv(variable);
env[0] = '\0';
if (temp != NULL)
ExpandEnvironmentStrings(temp, env, sizeof(env));
#else
#ifdef VMS
char *env = getenv(variable);
if (env && strcmp("HOME",variable) == 0) {
env = decc$translate_vms(env);
}
#else
/* no length control */
char *env = getenv(variable);
#endif
#endif
return (env && env[0])?strdup(env):NULL;
}
char *curl_getenv(const char *v)
{
return GetEnv(v);
}

174
Utilities/cmcurl/getinfo.c Normal file
View File

@ -0,0 +1,174 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <curl/curl.h>
#include "urldata.h"
#include "getinfo.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "curl_memory.h"
/* Make this the last #include */
#include "memdebug.h"
/*
* This is supposed to be called in the beginning of a permform() session
* and should reset all session-info variables
*/
CURLcode Curl_initinfo(struct SessionHandle *data)
{
struct Progress *pro = &data->progress;
struct PureInfo *info =&data->info;
pro->t_nslookup = 0;
pro->t_connect = 0;
pro->t_pretransfer = 0;
pro->t_starttransfer = 0;
pro->timespent = 0;
pro->t_redirect = 0;
info->httpcode = 0;
info->httpversion=0;
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
if (info->contenttype)
free(info->contenttype);
info->contenttype = NULL;
info->header_size = 0;
info->request_size = 0;
return CURLE_OK;
}
CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
{
va_list arg;
long *param_longp=NULL;
double *param_doublep=NULL;
char **param_charp=NULL;
va_start(arg, info);
switch(info&CURLINFO_TYPEMASK) {
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
case CURLINFO_STRING:
param_charp = va_arg(arg, char **);
if(NULL == param_charp)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLINFO_LONG:
param_longp = va_arg(arg, long *);
if(NULL == param_longp)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLINFO_DOUBLE:
param_doublep = va_arg(arg, double *);
if(NULL == param_doublep)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
switch(info) {
case CURLINFO_EFFECTIVE_URL:
*param_charp = data->change.url?data->change.url:(char *)"";
break;
case CURLINFO_RESPONSE_CODE:
*param_longp = data->info.httpcode;
break;
case CURLINFO_HTTP_CONNECTCODE:
*param_longp = data->info.httpproxycode;
break;
case CURLINFO_FILETIME:
*param_longp = data->info.filetime;
break;
case CURLINFO_HEADER_SIZE:
*param_longp = data->info.header_size;
break;
case CURLINFO_REQUEST_SIZE:
*param_longp = data->info.request_size;
break;
case CURLINFO_TOTAL_TIME:
*param_doublep = data->progress.timespent;
break;
case CURLINFO_NAMELOOKUP_TIME:
*param_doublep = data->progress.t_nslookup;
break;
case CURLINFO_CONNECT_TIME:
*param_doublep = data->progress.t_connect;
break;
case CURLINFO_PRETRANSFER_TIME:
*param_doublep = data->progress.t_pretransfer;
break;
case CURLINFO_STARTTRANSFER_TIME:
*param_doublep = data->progress.t_starttransfer;
break;
case CURLINFO_SIZE_UPLOAD:
*param_doublep = (double)data->progress.uploaded;
break;
case CURLINFO_SIZE_DOWNLOAD:
*param_doublep = (double)data->progress.downloaded;
break;
case CURLINFO_SPEED_DOWNLOAD:
*param_doublep = (double)data->progress.dlspeed;
break;
case CURLINFO_SPEED_UPLOAD:
*param_doublep = (double)data->progress.ulspeed;
break;
case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->set.ssl.certverifyresult;
break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
*param_doublep = (double)data->progress.size_dl;
break;
case CURLINFO_CONTENT_LENGTH_UPLOAD:
*param_doublep = (double)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;
case CURLINFO_PRIVATE:
*param_charp = data->set.private;
break;
case CURLINFO_HTTPAUTH_AVAIL:
*param_longp = data->info.httpauthavail;
break;
case CURLINFO_PROXYAUTH_AVAIL:
*param_longp = data->info.proxyauthavail;
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}
return CURLE_OK;
}

View File

@ -0,0 +1,28 @@
#ifndef __GETINFO_H
#define __GETINFO_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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_getinfo(struct SessionHandle *data, CURLINFO info, ...);
CURLcode Curl_initinfo(struct SessionHandle *data);
#endif

267
Utilities/cmcurl/hash.c Normal file
View File

@ -0,0 +1,267 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <stdlib.h>
#include "hash.h"
#include "llist.h"
#include "curl_memory.h"
/* this must be the last include file */
#include "memdebug.h"
static unsigned long
hash_str(const char *key, size_t key_length)
{
char *end = (char *) key + key_length;
unsigned long h = 5381;
while (key < end) {
h += h << 5;
h ^= (unsigned long) *key++;
}
return h;
}
static void
hash_element_dtor(void *user, void *element)
{
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);
}
/* return 1 on error, 0 is fine */
int
Curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
{
int i;
h->dtor = dtor;
h->size = 0;
h->slots = slots;
h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *));
if(h->table) {
for (i = 0; i < slots; ++i) {
h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
if(!h->table[i]) {
while(i--)
Curl_llist_destroy(h->table[i], NULL);
free(h->table);
return 1; /* failure */
}
}
return 0; /* fine */
}
else
return 1; /* failure */
}
curl_hash *
Curl_hash_alloc(int slots, curl_hash_dtor dtor)
{
curl_hash *h;
h = (curl_hash *) malloc(sizeof(curl_hash));
if (h) {
if(Curl_hash_init(h, slots, dtor)) {
/* failure */
free(h);
h = NULL;
}
}
return h;
}
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;
}
return 0;
}
static curl_hash_element *
mk_hash_element(char *key, size_t key_len, const void *p)
{
curl_hash_element *he =
(curl_hash_element *) malloc(sizeof(curl_hash_element));
if(he) {
char *dup = strdup(key);
if(dup) {
he->key = dup;
he->key_len = key_len;
he->ptr = (void *) p;
}
else {
/* failed to duplicate the key, free memory and fail */
free(he);
he = NULL;
}
}
return he;
}
#define find_slot(__h, __k, __k_len) (hash_str(__k, __k_len) % (__h)->slots)
#define FETCH_LIST(x,y,z) x->table[find_slot(x, y, z)]
/* Return the data in the hash. If there already was a match in the hash,
that data is returned. */
void *
Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p)
{
curl_hash_element *he;
curl_llist_element *le;
curl_llist *l = FETCH_LIST(h, key, key_len);
for (le = l->head; le; le = le->next) {
he = (curl_hash_element *) le->ptr;
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
h->dtor(p); /* remove the NEW entry */
return he->ptr; /* return the EXISTING entry */
}
}
he = mk_hash_element(key, key_len, p);
if (he) {
if(Curl_llist_insert_next(l, l->tail, he)) {
++h->size;
return p; /* return the new entry */
}
/*
* Couldn't insert it, destroy the 'he' element and the key again. We
* don't call hash_element_dtor() since that would also call the
* "destructor" for the actual data 'p'. When we fail, we shall not touch
* that data.
*/
free(he->key);
free(he);
}
return NULL; /* failure */
}
void *
Curl_hash_pick(curl_hash *h, char *key, size_t key_len)
{
curl_llist_element *le;
curl_hash_element *he;
curl_llist *l = FETCH_LIST(h, key, key_len);
for (le = l->head;
le;
le = le->next) {
he = le->ptr;
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
return he->ptr;
}
}
return NULL;
}
#if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
void
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 = (h->table[i])->head;
le;
le = le->next) {
curl_hash_element *el = le->ptr;
cb(user, el->ptr);
}
}
}
#endif
void
Curl_hash_clean(curl_hash *h)
{
int i;
for (i = 0; i < h->slots; ++i) {
Curl_llist_destroy(h->table[i], (void *) h);
}
free(h->table);
}
void
Curl_hash_clean_with_criterium(curl_hash *h, void *user,
int (*comp)(void *, void *))
{
curl_llist_element *le;
curl_llist_element *lnext;
curl_llist *list;
int i;
for (i = 0; i < h->slots; ++i) {
list = h->table[i];
le = list->head; /* get first list entry */
while(le) {
curl_hash_element *he = le->ptr;
lnext = le->next;
/* ask the callback function if we shall remove this entry or not */
if (comp(user, he->ptr)) {
Curl_llist_remove(list, le, (void *) h);
--h->size; /* one less entry in the hash now */
}
le = lnext;
}
}
}
void
Curl_hash_destroy(curl_hash *h)
{
if (!h)
return;
Curl_hash_clean(h);
free(h);
}

60
Utilities/cmcurl/hash.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef __HASH_H
#define __HASH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <stddef.h>
#include "llist.h"
typedef void (*curl_hash_dtor)(void *);
typedef struct _curl_hash {
curl_llist **table;
curl_hash_dtor dtor;
int slots;
size_t size;
} curl_hash;
typedef struct _curl_hash_element {
void *ptr;
char *key;
size_t key_len;
} curl_hash_element;
int Curl_hash_init(curl_hash *, int, curl_hash_dtor);
curl_hash *Curl_hash_alloc(int, curl_hash_dtor);
void *Curl_hash_add(curl_hash *, char *, size_t, 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

301
Utilities/cmcurl/hostares.c Normal file
View File

@ -0,0 +1,301 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for ares-enabled builds
**********************************************************************/
#ifdef CURLRES_ARES
/*
* Curl_fdset() is called when someone from the outside world (using
* curl_multi_fdset()) wants to get our fd_set setup and we're talking with
* ares. The caller must make sure that this function is only called when we
* have a working ares channel.
*
* Returns: CURLE_OK always!
*/
CURLcode Curl_fdset(struct connectdata *conn,
fd_set *read_fd_set,
fd_set *write_fd_set,
int *max_fdp)
{
int max = ares_fds(conn->data->state.areschannel,
read_fd_set, write_fd_set);
*max_fdp = max;
return CURLE_OK;
}
/*
* Curl_is_resolved() is called repeatedly to check if a previous name resolve
* request has completed. It should also make sure to time-out if the
* operation seems to take too long.
*
* Returns normal CURLcode errors.
*/
CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns)
{
fd_set read_fds, write_fds;
struct timeval tv={0,0};
struct SessionHandle *data = conn->data;
int nfds;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
(void)select(nfds, &read_fds, &write_fds, NULL,
(struct timeval *)&tv);
/* Call ares_process() unconditonally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
ares_process(data->state.areschannel, &read_fds, &write_fds);
*dns = NULL;
if(conn->async.done) {
/* we're done, kill the ares handle */
if(!conn->async.dns) {
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
ares_strerror(conn->async.status));
return CURLE_COULDNT_RESOLVE_HOST;
}
*dns = conn->async.dns;
}
return CURLE_OK;
}
/*
* Curl_wait_for_resolv() waits for a resolve to finish. This function should
* be avoided since using this risk getting the multi interface to "hang".
*
* If 'entry' is non-NULL, make it point to the resolved dns entry
*
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
* CURLE_OPERATION_TIMEDOUT if a time-out occurred.
*/
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
CURLcode rc=CURLE_OK;
struct SessionHandle *data = conn->data;
long timeout = CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
/* now, see if there's a connect timeout or a regular timeout to
use instead of the default one */
if(conn->data->set.connecttimeout)
timeout = conn->data->set.connecttimeout;
else if(conn->data->set.timeout)
timeout = conn->data->set.timeout;
/* We convert the number of seconds into number of milliseconds here: */
if(timeout < 2147483)
/* maximum amount of seconds that can be multiplied with 1000 and
still fit within 31 bits */
timeout *= 1000;
else
timeout = 0x7fffffff; /* ridiculous amount of time anyway */
/* Wait for the name resolve query to complete. */
while (1) {
int nfds=0;
fd_set read_fds, write_fds;
struct timeval *tvp, tv, store;
int count;
struct timeval now = Curl_tvnow();
long timediff;
store.tv_sec = (int)timeout/1000;
store.tv_usec = (timeout%1000)*1000;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
if (nfds == 0)
/* no file descriptors means we're done waiting */
break;
tvp = ares_timeout(data->state.areschannel, &store, &tv);
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
if (count < 0 && errno != EINVAL)
break;
ares_process(data->state.areschannel, &read_fds, &write_fds);
timediff = Curl_tvdiff(Curl_tvnow(), now); /* spent time */
timeout -= timediff?timediff:1; /* always deduct at least 1 */
if (timeout < 0) {
/* our timeout, so we cancel the ares operation */
ares_cancel(data->state.areschannel);
break;
}
}
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
if(entry)
*entry = conn->async.dns;
if(!conn->async.dns) {
/* a name was not resolved */
if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
failf(data, "Resolving host timed out: %s", conn->host.dispname);
rc = CURLE_OPERATION_TIMEDOUT;
}
else if(conn->async.done) {
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
ares_strerror(conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST;
}
else
rc = CURLE_OPERATION_TIMEDOUT;
/* close the connection, since we can't return failure here without
cleaning up this connection properly */
Curl_disconnect(conn);
}
return rc;
}
/*
* Curl_getaddrinfo() - when using ares
*
* Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the forth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
int port,
int *waitp)
{
char *bufp;
struct SessionHandle *data = conn->data;
in_addr_t in = inet_addr(hostname);
*waitp = FALSE;
if (in != CURL_INADDR_NONE) {
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(in, hostname, port);
}
bufp = strdup(hostname);
if(bufp) {
Curl_safefree(conn->async.hostname);
conn->async.hostname = bufp;
conn->async.port = port;
conn->async.done = FALSE; /* not done */
conn->async.status = 0; /* clear */
conn->async.dns = NULL; /* clear */
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname(data->state.areschannel, hostname, PF_INET,
Curl_addrinfo4_callback, conn);
*waitp = TRUE; /* please wait for the response */
}
return NULL; /* no struct yet */
}
#endif /* CURLRES_ARES */

170
Utilities/cmcurl/hostasyn.c Normal file
View File

@ -0,0 +1,170 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for builds using asynchronous name resolves
**********************************************************************/
#ifdef CURLRES_ASYNCH
/*
* addrinfo_callback() gets called by ares, gethostbyname_thread() or
* getaddrinfo_thread() when we got the name resolved (or not!).
*
* If the status argument is CURL_ASYNC_SUCCESS, we might need to copy the
* address field since it might be freed when this function returns. This
* operation stores the resolved data in the DNS cache.
*
* NOTE: for IPv6 operations, Curl_addrinfo_copy() returns the same
* pointer it is given as argument!
*
* The storage operation locks and unlocks the DNS cache.
*/
static void addrinfo_callback(void *arg, /* "struct connectdata *" */
int status,
void *addr)
{
struct connectdata *conn = (struct connectdata *)arg;
struct Curl_dns_entry *dns = NULL;
conn->async.done = TRUE;
conn->async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
/*
* IPv4: Curl_addrinfo_copy() copies the address and returns an allocated
* version.
*
* IPv6: Curl_addrinfo_copy() returns the input pointer!
*/
Curl_addrinfo *ai = Curl_addrinfo_copy(addr, conn->async.port);
if(ai) {
struct SessionHandle *data = conn->data;
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
conn->async.hostname,
conn->async.port);
if(!dns)
/* failed to store, cleanup and return error */
Curl_freeaddrinfo(ai);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
}
conn->async.dns = dns;
/* ipv4: The input hostent struct will be freed by ares when we return from
this function */
}
void Curl_addrinfo4_callback(void *arg, /* "struct connectdata *" */
int status,
struct hostent *hostent)
{
addrinfo_callback(arg, status, hostent);
}
#ifdef CURLRES_IPV6
void Curl_addrinfo6_callback(void *arg, /* "struct connectdata *" */
int status,
struct addrinfo *ai)
{
addrinfo_callback(arg, status, ai);
}
#endif
#endif /* CURLRES_ASYNC */

540
Utilities/cmcurl/hostip.c Normal file
View File

@ -0,0 +1,540 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "inet_ntop.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/*
* hostip.c explained
* ==================
*
* The main COMPILE-TIME DEFINES to keep in mind when reading the host*.c
* source file are these:
*
* CURLRES_IPV6 - this host has getaddrinfo() and family, and thus we use
* that. The host may not be able to resolve IPv6, but we don't really have to
* take that into account. Hosts that aren't IPv6-enabled have CURLRES_IPV4
* defined.
*
* CURLRES_ARES - is defined if libcurl is built to use c-ares for
* asynchronous name resolves. It cannot have ENABLE_IPV6 defined at the same
* time, as c-ares has no ipv6 support. This can be Windows or *nix.
*
* CURLRES_THREADED - is defined if libcurl is built to run under (native)
* Windows, and then the name resolve will be done in a new thread, and the
* supported API will be the same as for ares-builds.
*
* If any of the two previous are defined, CURLRES_ASYNCH is defined too. If
* libcurl is not built to use an asynchronous resolver, CURLRES_SYNCH is
* defined.
*
* The host*.c sources files are split up like this:
*
* hostip.c - method-independent resolver functions and utility functions
* hostasyn.c - functions for asynchronous name resolves
* hostsyn.c - functions for synchronous name resolves
* hostares.c - functions for ares-using name resolves
* hostthre.c - functions for threaded name resolves
* hostip4.c - ipv4-specific functions
* hostip6.c - ipv6-specific functions
*
* The hostip.h is the united header file for all this. It defines the
* CURLRES_* defines based on the config*.h and setup.h defines.
*/
/* These two symbols are for the global DNS cache */
static curl_hash hostname_cache;
static int host_cache_initialized;
static void freednsentry(void *freethis);
/*
* Curl_global_host_cache_init() initializes and sets up a global DNS cache.
* Global DNS cache is general badness. Do not use. This will be removed in
* a future version. Use the share interface instead!
*/
void Curl_global_host_cache_init(void)
{
if (!host_cache_initialized) {
Curl_hash_init(&hostname_cache, 7, freednsentry);
host_cache_initialized = 1;
}
}
/*
* Return a pointer to the global cache
*/
curl_hash *Curl_global_host_cache_get(void)
{
return &hostname_cache;
}
/*
* Destroy and cleanup the global DNS cache
*/
void Curl_global_host_cache_dtor(void)
{
if (host_cache_initialized) {
Curl_hash_clean(&hostname_cache);
host_cache_initialized = 0;
}
}
/*
* Return # of adresses in a Curl_addrinfo struct
*/
int Curl_num_addresses(const Curl_addrinfo *addr)
{
int i;
for (i = 0; addr; addr = addr->ai_next, i++);
return i;
}
#define GET_SIN_ADDR_FROM_CURL_ADDRINFO(ai_addr, si, sin, sinaddr, ip) \
{ \
union { \
struct si* vsi; \
struct sin* vsin;\
} vi; \
vi.vsi = ai_addr; \
ip = &(vi.vsin->sinaddr); \
}
/*
* Curl_printable_address() returns a printable version of the 1st address
* given in the 'ip' argument. The result will be stored in the buf that is
* bufsize bytes big.
*
* If the conversion fails, it returns NULL.
*/
const char *Curl_printable_address(const Curl_addrinfo *ip,
char *buf, size_t bufsize)
{
int af = ip->ai_family;
const void *ip4;
#ifdef CURLRES_IPV6
const void *ip6;
GET_SIN_ADDR_FROM_CURL_ADDRINFO(ip->ai_addr, sockaddr, sockaddr_in6,
sin6_addr, ip6);
#else
const void *ip6 = NULL;
#endif
GET_SIN_ADDR_FROM_CURL_ADDRINFO(ip->ai_addr, sockaddr, sockaddr_in,
sin_addr, ip4);
return Curl_inet_ntop(af, af == AF_INET ? ip4 : ip6, buf, bufsize);
}
/*
* Return a hostcache id string for the providing host + port, to be used by
* the DNS caching.
*/
static char *
create_hostcache_id(char *server, int port)
{
/* create and return the new allocated entry */
return aprintf("%s:%d", server, port);
}
struct hostcache_prune_data {
int cache_timeout;
time_t now;
};
/*
* This function is set as a callback to be called for every entry in the DNS
* cache when we want to prune old unused entries.
*
* Returning non-zero means remove the entry, return 0 to keep it in the
* cache.
*/
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;
}
/*
* Prune the DNS cache. This assumes that a lock has already been taken.
*/
static void
hostcache_prune(curl_hash *hostcache, int cache_timeout, time_t 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);
}
/*
* Library-wide function for pruning the DNS cache. This function takes and
* returns the appropriate locks.
*/
void Curl_hostcache_prune(struct SessionHandle *data)
{
time_t now;
if(data->set.dns_cache_timeout == -1)
/* cache forever means never prune! */
return;
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
time(&now);
/* Remove outdated and unused entries from the hostcache */
hostcache_prune(data->hostcache,
data->set.dns_cache_timeout,
now);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
#ifdef HAVE_SIGSETJMP
/* Beware this is a global and unique instance. This is used to store the
return address that we can jump back to from inside a signal handler. This
is not thread-safe stuff. */
sigjmp_buf curl_jmpenv;
#endif
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
* When calling Curl_resolv() has resulted in a response with a returned
* address, we call this function to store the information in the dns
* cache etc
*
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
*/
struct Curl_dns_entry *
Curl_cache_addr(struct SessionHandle *data,
Curl_addrinfo *addr,
char *hostname,
int port)
{
char *entry_id;
size_t entry_len;
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
time_t now;
/* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if (!entry_id)
return NULL;
entry_len = strlen(entry_id);
/* Create a new cache entry */
dns = (struct Curl_dns_entry *) malloc(sizeof(struct Curl_dns_entry));
if (!dns) {
free(entry_id);
return NULL;
}
dns->inuse = 0; /* init to not used */
dns->addr = addr; /* this is the address(es) */
/* Store the resolved data in our DNS cache. This function may return a
pointer to an existing struct already present in the hash, and it may
return the same argument we pass in. Make no assumptions. */
dns2 = Curl_hash_add(data->hostcache, entry_id, entry_len+1, (void *)dns);
if(!dns2) {
/* Major badness, run away. */
free(dns);
free(entry_id);
return NULL;
}
time(&now);
dns = dns2;
dns->timestamp = now; /* used now */
dns->inuse++; /* mark entry as in-use */
/* free the allocated entry_id again */
free(entry_id);
return dns;
}
/*
* Curl_resolv() is the main name resolve function within libcurl. It resolves
* a name and returns a pointer to the entry in the 'entry' argument (if one
* is provided). This function might return immediately if we're using asynch
* resolves. See the return codes.
*
* The cache entry we return will get its 'inuse' counter increased when this
* function is used. You MUST call Curl_resolv_unlock() later (when you're
* done using this struct) to decrease the counter again.
*
* Return codes:
*
* CURLRESOLV_ERROR (-1) = error, no pointer
* CURLRESOLV_RESOLVED (0) = OK, pointer provided
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
*/
int Curl_resolv(struct connectdata *conn,
char *hostname,
int port,
struct Curl_dns_entry **entry)
{
char *entry_id;
struct Curl_dns_entry *dns = NULL;
size_t entry_len;
int wait;
struct SessionHandle *data = conn->data;
CURLcode result;
/* default to failure */
int rc;
*entry = NULL;
#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 timed out");
return CURLRESOLV_ERROR;
}
#endif
rc = CURLRESOLV_ERROR;
/* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if (!entry_id)
return CURLRESOLV_ERROR;
entry_len = strlen(entry_id);
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* See if its already in our dns cache */
dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
/* free the allocated entry_id again */
free(entry_id);
if (!dns) {
/* The entry was not in the cache. Resolve it to IP address */
Curl_addrinfo *addr;
/* Check what IP specifics the app has requested and if we can provide it.
* If not, bail out. */
if(!Curl_ipvalid(data))
return CURLRESOLV_ERROR;
/* If Curl_getaddrinfo() returns NULL, 'wait' might be set to a non-zero
value indicating that we need to wait for the response to the resolve
call */
addr = Curl_getaddrinfo(conn, hostname, port, &wait);
if (!addr) {
if(wait) {
/* the response to our resolve call will come asynchronously at
a later time, good or bad */
/* First, check that we haven't received the info by now */
result = Curl_is_resolved(conn, &dns);
if(result) /* error detected */
return CURLRESOLV_ERROR;
if(dns)
rc = CURLRESOLV_RESOLVED; /* pointer provided */
else
rc = CURLRESOLV_PENDING; /* no info yet */
}
}
else {
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* we got a response, store it in the cache */
dns = Curl_cache_addr(data, addr, hostname, port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
if(!dns)
/* returned failure, bail out nicely */
Curl_freeaddrinfo(addr);
else
rc = CURLRESOLV_RESOLVED;
}
}
else {
dns->inuse++; /* we use it! */
rc = CURLRESOLV_RESOLVED;
}
*entry = dns;
return rc;
}
/*
* Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
* made, the struct may be destroyed due to pruning. It is important that only
* one unlock is made for each Curl_resolv() call.
*/
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
{
curlassert(dns && (dns->inuse>0));
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns->inuse--;
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
/*
* File-internal: free a cache dns entry.
*/
static void freednsentry(void *freethis)
{
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
Curl_freeaddrinfo(p->addr);
free(p);
}
/*
* Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
*/
curl_hash *Curl_mk_dnscache(void)
{
return Curl_hash_alloc(7, freednsentry);
}
#ifdef CURLRES_ADDRINFO_COPY
/* align on even 64bit boundaries */
#define MEMALIGN(x) ((x)+(8-(((unsigned long)(x))&0x7)))
/*
* Curl_addrinfo_copy() performs a "deep" copy of a hostent into a buffer and
* returns a pointer to the malloc()ed copy. You need to call free() on the
* returned buffer when you're done with it.
*/
Curl_addrinfo *Curl_addrinfo_copy(void *org, int port)
{
struct hostent *orig = org;
return Curl_he2ai(orig, port);
}
#endif /* CURLRES_ADDRINFO_COPY */

255
Utilities/cmcurl/hostip.h Normal file
View File

@ -0,0 +1,255 @@
#ifndef __HOSTIP_H
#define __HOSTIP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include "hash.h"
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
/*
* Setup comfortable CURLRES_* defines to use in the host*.c sources.
*/
#ifdef USE_ARES
#define CURLRES_ASYNCH
#define CURLRES_ARES
#endif
#ifdef USE_THREADING_GETHOSTBYNAME
#define CURLRES_ASYNCH
#define CURLRES_THREADED
#endif
#ifdef USE_THREADING_GETADDRINFO
#define CURLRES_ASYNCH
#define CURLRES_THREADED
#endif
#ifdef ENABLE_IPV6
#define CURLRES_IPV6
#else
#define CURLRES_IPV4
#endif
#ifdef CURLRES_IPV4
#if !defined(HAVE_GETHOSTBYNAME_R) || defined(CURLRES_ASYNCH)
/* If built for ipv4 and missing gethostbyname_r(), or if using async name
resolve, we need the Curl_addrinfo_copy() function (which itself needs the
Curl_hostent_relocate() function)) */
#define CURLRES_ADDRINFO_COPY
#endif
#endif /* IPv4-only */
#ifndef CURLRES_ASYNCH
#define CURLRES_SYNCH
#endif
#ifndef USE_LIBIDN
#define CURLRES_IDN
#endif
/* Allocate enough memory to hold the full name information structs and
* 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 edition, p. 304: 8192 bytes!
*/
#define CURL_HOSTENT_SIZE 9000
#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this
many seconds for a name resolve */
#ifdef CURLRES_ARES
#define CURL_ASYNC_SUCCESS ARES_SUCCESS
#else
#define CURL_ASYNC_SUCCESS CURLE_OK
#endif
/*
* Curl_addrinfo MUST be used for all name resolved info.
*/
#ifdef CURLRES_IPV6
typedef struct addrinfo Curl_addrinfo;
#else
/* OK, so some ipv4-only include tree probably have the addrinfo struct, but
to work even on those that don't, we provide our own look-alike! */
struct Curl_addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct Curl_addrinfo *ai_next;
};
typedef struct Curl_addrinfo Curl_addrinfo;
#endif
struct addrinfo;
struct SessionHandle;
struct connectdata;
void Curl_global_host_cache_init(void);
void Curl_global_host_cache_dtor(void);
curl_hash *Curl_global_host_cache_get(void);
#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
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 */
};
/*
* 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!
*/
/* return codes */
#define CURLRESOLV_ERROR -1
#define CURLRESOLV_RESOLVED 0
#define CURLRESOLV_PENDING 1
int Curl_resolv(struct connectdata *conn, char *hostname,
int port, struct Curl_dns_entry **dnsentry);
/*
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
bool Curl_ipvalid(struct SessionHandle *data);
/*
* Curl_getaddrinfo() is the generic low-level name resolve API within this
* source file. There are several versions of this function - for different
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
int port,
int *waitp);
CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns);
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **dnsentry);
/* Curl_fdset() is a generic function that exists in multiple versions
depending on what name resolve technology we've built to use. The function
is called from the curl_multi_fdset() function */
CURLcode Curl_fdset(struct connectdata *conn,
fd_set *read_fd_set,
fd_set *write_fd_set,
int *max_fdp);
/* unlock a previously resolved dns entry */
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns);
/* for debugging purposes only: */
void Curl_scan_cache_used(void *user, void *ptr);
/* free name info */
void Curl_freeaddrinfo(Curl_addrinfo *freeaddr);
/* make a new dns cache and return the handle */
curl_hash *Curl_mk_dnscache(void);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct SessionHandle *data);
/* Return # of adresses in a Curl_addrinfo struct */
int Curl_num_addresses (const Curl_addrinfo *addr);
#ifdef CURLDEBUG
void curl_dofreeaddrinfo(struct addrinfo *freethis,
int line, const char *source);
int curl_dogetaddrinfo(char *hostname, char *service,
struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source);
int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags,
int line, const char *source);
#endif
/* This is the callback function that is used when we build with asynch
resolve, ipv4 */
void Curl_addrinfo4_callback(void *arg,
int status,
struct hostent *hostent);
/* This is the callback function that is used when we build with asynch
resolve, ipv6 */
void Curl_addrinfo6_callback(void *arg,
int status,
struct addrinfo *ai);
/* [ipv4 only] Creates a Curl_addrinfo struct from a numerical-only IP
address */
Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname, int port);
/* [ipv4 only] Curl_he2ai() converts a struct hostent to a Curl_addrinfo chain
and returns it */
Curl_addrinfo *Curl_he2ai(struct hostent *, int port);
/* relocate a hostent struct */
void Curl_hostent_relocate(struct hostent *h, long offset);
/* Clone a Curl_addrinfo struct, works protocol independently */
Curl_addrinfo *Curl_addrinfo_copy(void *orig, int port);
/*
* Curl_printable_address() returns a printable version of the 1st address
* given in the 'ip' argument. The result will be stored in the buf that is
* bufsize bytes big.
*/
const char *Curl_printable_address(const Curl_addrinfo *ip,
char *buf, size_t bufsize);
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
*/
struct Curl_dns_entry *
Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
char *hostname, int port);
#ifndef INADDR_NONE
#define CURL_INADDR_NONE (in_addr_t) ~0
#else
#define CURL_INADDR_NONE INADDR_NONE
#endif
#endif

456
Utilities/cmcurl/hostip4.c Normal file
View File

@ -0,0 +1,456 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for plain-ipv4 builds
**********************************************************************/
#ifdef CURLRES_IPV4 /* plain ipv4 code coming up */
/*
* This is a function for freeing name information in a protocol independent
* way.
*/
void Curl_freeaddrinfo(Curl_addrinfo *ai)
{
Curl_addrinfo *next;
/* walk over the list and free all entries */
while(ai) {
next = ai->ai_next;
free(ai);
ai = next;
}
}
/*
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
bool Curl_ipvalid(struct SessionHandle *data)
{
if(data->set.ip_version == CURL_IPRESOLVE_V6)
/* an ipv6 address was requested and we can't get/use one */
return FALSE;
return TRUE; /* OK, proceed */
}
struct namebuf {
struct hostent hostentry;
char *h_addr_list[2];
struct in_addr addrentry;
char h_name[16]; /* 123.123.123.123 = 15 letters is maximum */
};
/*
* Curl_ip2addr() takes a 32bit ipv4 internet address as input parameter
* together with a pointer to the string version of the address, and it
* returns a Curl_addrinfo chain filled in correctly with information for this
* address/host.
*
* The input parameters ARE NOT checked for validity but they are expected
* to have been checked already when this is called.
*/
Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname, int port)
{
Curl_addrinfo *ai;
struct hostent *h;
struct in_addr *addrentry;
struct namebuf buffer;
struct namebuf *buf = &buffer;
h = &buf->hostentry;
h->h_addr_list = &buf->h_addr_list[0];
addrentry = &buf->addrentry;
addrentry->s_addr = num;
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 = &buf->h_name[0];
h->h_aliases = NULL;
/* Now store the dotted version of the address */
snprintf((char*)(h->h_name), 16, "%s", hostname);
ai = Curl_he2ai(h, port);
return ai;
}
#ifdef CURLRES_SYNCH /* the functions below are for synchronous resolves */
/*
* Curl_getaddrinfo() - the ipv4 synchronous version.
*
* 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.
*
* gethostbyname_r() is the thread-safe version of the gethostbyname()
* function. When we build for plain IPv4, we attempt to use this
* function. There are _three_ different gethostbyname_r() versions, and we
* detect which one this platform supports in the configure script and set up
* the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or
* HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME
* has the corresponding rules. This is primarily on *nix. Note that some unix
* flavours have thread-safe versions of the plain gethostbyname() etc.
*
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
int port,
int *waitp)
{
Curl_addrinfo *ai = NULL;
struct hostent *h = NULL;
in_addr_t in;
struct SessionHandle *data = conn->data;
struct hostent *buf = NULL;
(void)port; /* unused in IPv4 code */
*waitp = 0; /* don't wait, we act synchronously */
in=inet_addr(hostname);
if (in != CURL_INADDR_NONE) {
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(in, hostname, port);
}
#if defined(HAVE_GETHOSTBYNAME_R)
/*
* gethostbyname_r() is the preferred resolve function for many platforms.
* Since there are three different versions of it, the following code is
* somewhat #ifdef-ridden.
*/
else {
int h_errnop;
int res=ERANGE;
buf = (struct hostent *)calloc(CURL_HOSTENT_SIZE, 1);
if(!buf)
return NULL; /* major failure */
/*
* The clearing of the buffer is a workaround for a gethostbyname_r bug in
* qnx nto and it is also _required_ for some of these functions on some
* platforms.
*/
#ifdef HAVE_GETHOSTBYNAME_R_5
/* Solaris, IRIX and more */
(void)res; /* prevent compiler warning */
h = gethostbyname_r(hostname,
(struct hostent *)buf,
(char *)buf + sizeof(struct hostent),
CURL_HOSTENT_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) {
;
}
else
#endif /* HAVE_GETHOSTBYNAME_R_5 */
#ifdef HAVE_GETHOSTBYNAME_R_6
/* Linux */
res=gethostbyname_r(hostname,
(struct hostent *)buf,
(char *)buf + sizeof(struct hostent),
CURL_HOSTENT_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 returns EAGAIN if the given buffer size is too
* small. Previous versions are known to return ERANGE for the same
* problem.
*
* This wouldn't be such a big problem if older versions wouldn't
* sometimes return EAGAIN on a common failure case. Alas, we can't
* assume that EAGAIN *or* ERANGE means ERANGE for any given version of
* glibc.
*
* For now, we do that and thus we may call the function repeatedly and
* fail for older glibc versions that return EAGAIN, until we run out of
* buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
*
* If anyone has a better fix, please tell us!
*
* -------------------------------------------------------------------
*
* On October 23rd 2003, Dan C dug up more details on the mysteries of
* gethostbyname_r() in glibc:
*
* In glibc 2.2.5 the interface is different (this has also been
* discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
* explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
* (shipped/upgraded by Redhat 7.2) don't show this behavior!
*
* In this "buggy" version, the return code is -1 on error and 'errno'
* is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
* thread-safe variable.
*/
if(!h) /* failure */
#endif/* HAVE_GETHOSTBYNAME_R_6 */
#ifdef HAVE_GETHOSTBYNAME_R_3
/* AIX, Digital Unix/Tru64, HPUX 10, more? */
/* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
* the plain fact that it does not return unique full buffers on each
* call, but instead several of the pointers in the hostent structs will
* point to the same actual data! This have the unfortunate down-side that
* our caching system breaks down horribly. Luckily for us though, AIX 4.3
* and more recent versions have a "completely thread-safe"[*] libc where
* all the data is stored in thread-specific memory areas making calls to
* the plain old gethostbyname() work fine even for multi-threaded
* programs.
*
* This AIX 4.3 or later detection is all made in the configure script.
*
* Troels Walsted Hansen helped us work this out on March 3rd, 2003.
*
* [*] = much later we've found out that it isn't at all "completely
* thread-safe", but at least the gethostbyname() function is.
*/
if(CURL_HOSTENT_SIZE >=
(sizeof(struct hostent)+sizeof(struct hostent_data))) {
/* August 22nd, 2000: Albert Chin-A-Young brought an updated version
* that should work! September 20: Richard Prescott worked on the buffer
* size dilemma.
*/
res = gethostbyname_r(hostname,
(struct hostent *)buf,
(struct hostent_data *)((char *)buf +
sizeof(struct hostent)));
h_errnop= errno; /* we don't deal with this, but set it anyway */
}
else
res = -1; /* failure, too smallish buffer size */
if(!res) { /* success */
h = buf; /* result expected in h */
/* This is the worst kind of the different gethostbyname_r() interfaces.
* Since we don't know how big buffer this particular lookup required,
* we can't realloc down the huge alloc without doing closer analysis of
* the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
* name lookup. Fixing this would require an extra malloc() and then
* calling Curl_addrinfo_copy() that subsequent realloc()s down the new
* memory area to the actually used amount.
*/
}
else
#endif /* HAVE_GETHOSTBYNAME_R_3 */
{
infof(data, "gethostbyname_r(2) failed for %s\n", hostname);
h = NULL; /* set return code to NULL */
free(buf);
}
#else /* HAVE_GETHOSTBYNAME_R */
/*
* Here is code for platforms that don't have gethostbyname_r() or for
* which the gethostbyname() is the preferred() function.
*/
else {
h = gethostbyname(hostname);
if (!h)
infof(data, "gethostbyname(2) failed for %s\n", hostname);
#endif /*HAVE_GETHOSTBYNAME_R */
}
if(h) {
ai = Curl_he2ai(h, port);
if (buf) /* used a *_r() function */
free(buf);
}
return ai;
}
#endif /* CURLRES_SYNCH */
/*
* Curl_he2ai() translates from a hostent struct to a Curl_addrinfo struct.
* The Curl_addrinfo is meant to work like the addrinfo struct does for IPv6
* stacks, but for all hosts and environments.
struct Curl_addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
struct hostent {
char *h_name; * official name of host *
char **h_aliases; * alias list *
int h_addrtype; * host address type *
int h_length; * length of address *
char **h_addr_list; * list of addresses *
}
#define h_addr h_addr_list[0] * for backward compatibility *
*/
Curl_addrinfo *Curl_he2ai(struct hostent *he, int port)
{
Curl_addrinfo *ai;
Curl_addrinfo *prevai = NULL;
Curl_addrinfo *firstai = NULL;
int i;
union {
struct in_addr *addr;
char* list;
} curr;
union {
struct sockaddr_in* addr_in;
struct sockaddr* addr;
} address;
if(!he)
/* no input == no output! */
return NULL;
for(i=0; (curr.list = he->h_addr_list[i]); i++) {
ai = calloc(1, sizeof(Curl_addrinfo) + sizeof(struct sockaddr_in));
if(!ai)
break;
if(!firstai)
/* store the pointer we want to return from this function */
firstai = ai;
if(prevai)
/* make the previous entry point to this */
prevai->ai_next = ai;
ai->ai_family = AF_INET; /* we only support this */
ai->ai_socktype = SOCK_STREAM; /* we only support this */
ai->ai_addrlen = sizeof(struct sockaddr_in);
/* make the ai_addr point to the address immediately following this struct
and use that area to store the address */
ai->ai_addr = (struct sockaddr *) (ai + 1);
/* leave the rest of the struct filled with zero */
address.addr = ai->ai_addr; /* storage area for this info */
memcpy((char *)&(address.addr_in->sin_addr), curr.addr, sizeof(struct in_addr));
address.addr_in->sin_family = he->h_addrtype;
address.addr_in->sin_port = htons((unsigned short)port);
prevai = ai;
}
return firstai;
}
#endif /* CURLRES_IPV4 */

263
Utilities/cmcurl/hostip6.c Normal file
View File

@ -0,0 +1,263 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for ipv6-enabled builds
**********************************************************************/
#ifdef CURLRES_IPV6
/*
* This is a wrapper function for freeing name information in a protocol
* independent way. This takes care of using the appropriate underlaying
* function.
*/
void Curl_freeaddrinfo(Curl_addrinfo *p)
{
freeaddrinfo(p);
}
#ifdef CURLRES_ASYNCH
/*
* Curl_addrinfo_copy() is used by the asynch callback to copy a given
* address. But this is an ipv6 build and then we don't copy the address, we
* just return the same pointer!
*/
Curl_addrinfo *Curl_addrinfo_copy(void *source, int port)
{
(void) port;
return source;
}
#endif
#ifdef CURLDEBUG
/* These are strictly for memory tracing and are using the same style as the
* family otherwise present in memdebug.c. I put these ones here since they
* require a bunch of structs I didn't wanna include in memdebug.c
*/
int curl_dogetaddrinfo(char *hostname, char *service,
struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source)
{
int res=(getaddrinfo)(hostname, service, hints, result);
if(0 == res) {
/* success */
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
source, line, (void *)*result);
}
else {
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
source, line);
}
return res;
}
int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags,
int line, const char *source)
{
int res=(getnameinfo)(sa, salen, host, hostlen, serv, servlen, flags);
if(0 == res) {
/* success */
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo()\n",
source, line);
}
else {
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo() failed = %d\n",
source, line, res);
}
return res;
}
void curl_dofreeaddrinfo(struct addrinfo *freethis,
int line, const char *source)
{
(freeaddrinfo)(freethis);
if(logfile)
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
source, line, (void *)freethis);
}
#endif
/*
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
bool Curl_ipvalid(struct SessionHandle *data)
{
if(data->set.ip_version == CURL_IPRESOLVE_V6) {
/* see if we have an IPv6 stack */
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s == CURL_SOCKET_BAD)
/* an ipv6 address was requested and we can't get/use one */
return FALSE;
sclose(s);
}
return TRUE;
}
#ifndef USE_THREADING_GETADDRINFO
/*
* Curl_getaddrinfo() when built ipv6-enabled (non-threading version).
*
* Returns name information about the given hostname and port number. If
* successful, the 'addrinfo' is returned and the forth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
int port,
int *waitp)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
curl_socket_t s;
int pf;
struct SessionHandle *data = conn->data;
*waitp=0; /* don't wait, we have the response now */
/* 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);
/*
* Check if a more limited name resolve has been requested.
*/
switch(data->set.ip_version) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
case CURL_IPRESOLVE_V6:
pf = PF_INET6;
break;
default:
pf = PF_UNSPEC;
break;
}
}
memset(&hints, 0, sizeof(hints));
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:%d\n", hostname, port);
return NULL;
}
return res;
}
#endif /* USE_THREADING_GETADDRINFO */
#endif /* ipv6 */

149
Utilities/cmcurl/hostsyn.c Normal file
View File

@ -0,0 +1,149 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for builds using synchronous name resolves
**********************************************************************/
#ifdef CURLRES_SYNCH
/*
* Curl_wait_for_resolv() for synch-builds. Curl_resolv() can never return
* wait==TRUE, so this function will never be called. If it still gets called,
* we return failure at once.
*
* We provide this function only to allow multi.c to remain unaware if we are
* doing asynch resolves or not.
*/
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
(void)conn;
*entry=NULL;
return CURLE_COULDNT_RESOLVE_HOST;
}
/*
* This function will never be called when synch-built. If it still gets
* called, we return failure at once.
*
* We provide this function only to allow multi.c to remain unaware if we are
* doing asynch resolves or not.
*/
CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns)
{
(void)conn;
*dns = NULL;
return CURLE_COULDNT_RESOLVE_HOST;
}
/*
* We just return OK, this function is never actually used for synch builds.
* It is present here to keep #ifdefs out from multi.c
*/
CURLcode Curl_fdset(struct connectdata *conn,
fd_set *read_fd_set,
fd_set *write_fd_set,
int *max_fdp)
{
(void)conn;
(void)read_fd_set;
(void)write_fd_set;
(void)max_fdp;
return CURLE_OK;
}
#endif /* truly sync */

551
Utilities/cmcurl/hostthre.c Normal file
View File

@ -0,0 +1,551 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "inet_ntop.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for Windows threaded name resolves builds
**********************************************************************/
#ifdef CURLRES_THREADED
/* This function is used to init a threaded resolve */
static bool init_resolve_thread(struct connectdata *conn,
const char *hostname, int port,
const Curl_addrinfo *hints);
#ifdef CURLRES_IPV4
#define THREAD_FUNC gethostbyname_thread
#define THREAD_NAME "gethostbyname_thread"
#else
#define THREAD_FUNC getaddrinfo_thread
#define THREAD_NAME "getaddrinfo_thread"
#endif
#if defined(DEBUG_THREADING_GETHOSTBYNAME) || \
defined(DEBUG_THREADING_GETADDRINFO)
/* If this is defined, provide tracing */
#define TRACE(args) \
do { trace_it("%u: ", __LINE__); trace_it args; } while (0)
static void trace_it (const char *fmt, ...)
{
static int do_trace = -1;
va_list args;
if (do_trace == -1) {
const char *env = getenv("CURL_TRACE");
do_trace = (env && atoi(env) > 0);
}
if (!do_trace)
return;
va_start (args, fmt);
vfprintf (stderr, fmt, args);
fflush (stderr);
va_end (args);
}
#else
#define TRACE(x)
#endif
#ifdef DEBUG_THREADING_GETADDRINFO
static void dump_addrinfo (struct connectdata *conn, const struct addrinfo *ai)
{
TRACE(("dump_addrinfo:\n"));
for ( ; ai; ai = ai->ai_next) {
char buf [INET6_ADDRSTRLEN];
trace_it(" fam %2d, CNAME %s, ",
ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
if (Curl_printable_address(ai, buf, sizeof(buf)))
trace_it("%s\n", buf);
else
trace_it("failed; %s\n", Curl_strerror(conn,WSAGetLastError()));
}
}
#endif
struct thread_data {
HANDLE thread_hnd;
unsigned thread_id;
DWORD thread_status;
curl_socket_t dummy_sock; /* dummy for Curl_fdset() */
FILE *stderr_file;
#ifdef CURLRES_IPV6
struct addrinfo hints;
#endif
};
#if defined(CURLRES_IPV4)
/*
* gethostbyname_thread() resolves a name, calls the Curl_addrinfo4_callback
* and then exits.
*
* For builds without ARES/ENABLE_IPV6, create a resolver thread and wait on
* it.
*/
static unsigned __stdcall gethostbyname_thread (void *arg)
{
struct connectdata *conn = (struct connectdata*) arg;
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
struct hostent *he;
int rc;
/* Sharing the same _iob[] element with our parent thread should
* hopefully make printouts synchronised. I'm not sure it works
* with a static runtime lib (MSVC's libc.lib).
*/
*stderr = *td->stderr_file;
WSASetLastError (conn->async.status = NO_DATA); /* pending status */
he = gethostbyname (conn->async.hostname);
if (he) {
Curl_addrinfo4_callback(conn, CURL_ASYNC_SUCCESS, he);
rc = 1;
}
else {
Curl_addrinfo4_callback(conn, (int)WSAGetLastError(), NULL);
rc = 0;
}
TRACE(("Winsock-error %d, addr %s\n", conn->async.status,
he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown"));
return (rc);
/* An implicit _endthreadex() here */
}
#elif defined(CURLRES_IPV6)
/*
* getaddrinfo_thread() resolves a name, calls Curl_addrinfo6_callback and then
* exits.
*
* For builds without ARES, but with ENABLE_IPV6, create a resolver thread
* and wait on it.
*/
static unsigned __stdcall getaddrinfo_thread (void *arg)
{
struct connectdata *conn = (struct connectdata*) arg;
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
struct addrinfo *res;
char service [NI_MAXSERV];
int rc;
*stderr = *td->stderr_file;
itoa(conn->async.port, service, 10);
WSASetLastError(conn->async.status = NO_DATA); /* pending status */
rc = getaddrinfo(conn->async.hostname, service, &td->hints, &res);
if (rc == 0) {
#ifdef DEBUG_THREADING_GETADDRINFO
dump_addrinfo (conn, res);
#endif
Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
}
else {
Curl_addrinfo6_callback(conn, (int)WSAGetLastError(), NULL);
TRACE(("Winsock-error %d, no address\n", conn->async.status));
}
return (rc);
/* An implicit _endthreadex() here */
}
#endif
/*
* destroy_thread_data() cleans up async resolver data.
* Complementary of ares_destroy.
*/
static void destroy_thread_data (struct Curl_async *async)
{
if (async->hostname)
free(async->hostname);
if (async->os_specific) {
curl_socket_t sock = ((const struct thread_data*)async->os_specific)->dummy_sock;
if (sock != CURL_SOCKET_BAD)
sclose(sock);
free(async->os_specific);
}
async->hostname = NULL;
async->os_specific = NULL;
}
/*
* init_resolve_thread() starts a new thread that performs the actual
* resolve. This function returns before the resolve is done.
*
* Returns FALSE in case of failure, otherwise TRUE.
*/
static bool init_resolve_thread (struct connectdata *conn,
const char *hostname, int port,
const Curl_addrinfo *hints)
{
struct thread_data *td = calloc(sizeof(*td), 1);
if (!td) {
SetLastError(ENOMEM);
return FALSE;
}
Curl_safefree(conn->async.hostname);
conn->async.hostname = strdup(hostname);
if (!conn->async.hostname) {
free(td);
SetLastError(ENOMEM);
return FALSE;
}
conn->async.port = port;
conn->async.done = FALSE;
conn->async.status = 0;
conn->async.dns = NULL;
conn->async.os_specific = (void*) td;
td->dummy_sock = CURL_SOCKET_BAD;
td->stderr_file = stderr;
td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, THREAD_FUNC,
conn, 0, &td->thread_id);
#ifdef CURLRES_IPV6
curlassert(hints);
td->hints = *hints;
#else
(void) hints;
#endif
if (!td->thread_hnd) {
SetLastError(errno);
TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn,errno)));
destroy_thread_data(&conn->async);
return FALSE;
}
/* This socket is only to keep Curl_fdset() and select() happy; should never
* become signalled for read/write since it's unbound but Windows needs
* atleast 1 socket in select().
*/
td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
return TRUE;
}
/*
* Curl_wait_for_resolv() waits for a resolve to finish. This function should
* be avoided since using this risk getting the multi interface to "hang".
*
* If 'entry' is non-NULL, make it point to the resolved dns entry
*
* This is the version for resolves-in-a-thread.
*/
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
struct SessionHandle *data = conn->data;
long timeout;
DWORD status, ticks;
CURLcode rc;
curlassert (conn && td);
/* now, see if there's a connect timeout or a regular timeout to
use instead of the default one */
timeout =
conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
conn->data->set.timeout ? conn->data->set.timeout :
CURL_TIMEOUT_RESOLVE; /* default name resolve timeout */
ticks = GetTickCount();
(void)ticks;
status = WaitForSingleObject(td->thread_hnd, 1000UL*timeout);
if (status == WAIT_OBJECT_0 || status == WAIT_ABANDONED) {
/* Thread finished before timeout; propagate Winsock error to this thread.
* 'conn->async.done = TRUE' is set in Curl_addrinfo4/6_callback().
*/
WSASetLastError(conn->async.status);
GetExitCodeThread(td->thread_hnd, &td->thread_status);
TRACE(("%s() status %lu, thread retval %lu, ",
THREAD_NAME, status, td->thread_status));
}
else {
conn->async.done = TRUE;
td->thread_status = (DWORD)-1;
TRACE(("%s() timeout, ", THREAD_NAME));
}
TRACE(("elapsed %lu ms\n", GetTickCount()-ticks));
CloseHandle(td->thread_hnd);
if(entry)
*entry = conn->async.dns;
rc = CURLE_OK;
if (!conn->async.dns) {
/* a name was not resolved */
if (td->thread_status == (DWORD)-1 || conn->async.status == NO_DATA) {
failf(data, "Resolving host timed out: %s", conn->host.name);
rc = CURLE_OPERATION_TIMEDOUT;
}
else if(conn->async.done) {
failf(data, "Could not resolve host: %s; %s",
conn->host.name, Curl_strerror(conn,conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST;
}
else
rc = CURLE_OPERATION_TIMEDOUT;
}
destroy_thread_data(&conn->async);
if(CURLE_OK != rc)
/* close the connection, since we must not return failure from here
without cleaning up this connection properly */
Curl_disconnect(conn);
return (rc);
}
/*
* Curl_is_resolved() is called repeatedly to check if a previous name resolve
* request has completed. It should also make sure to time-out if the
* operation seems to take too long.
*/
CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
*entry = NULL;
if (conn->async.done) {
/* we're done */
destroy_thread_data(&conn->async);
if (!conn->async.dns) {
TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n"));
return CURLE_COULDNT_RESOLVE_HOST;
}
*entry = conn->async.dns;
TRACE(("resolved okay, dns %p\n", *entry));
}
else
TRACE(("not yet\n"));
return CURLE_OK;
}
CURLcode Curl_fdset(struct connectdata *conn,
fd_set *read_fd_set,
fd_set *write_fd_set,
int *max_fdp)
{
const struct thread_data *td =
(const struct thread_data *) conn->async.os_specific;
if (td && td->dummy_sock != CURL_SOCKET_BAD) {
FD_SET(td->dummy_sock,write_fd_set);
*max_fdp = td->dummy_sock;
}
(void) read_fd_set;
return CURLE_OK;
}
#ifdef CURLRES_IPV4
/*
* Curl_getaddrinfo() - for Windows threading without ENABLE_IPV6.
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
int port,
int *waitp)
{
struct hostent *h;
struct SessionHandle *data = conn->data;
in_addr_t in;
*waitp = 0; /* don't wait, we act synchronously */
in = inet_addr(hostname);
if (in != CURL_INADDR_NONE)
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(in, hostname, port);
/* fire up a new resolver thread! */
if (init_resolve_thread(conn, hostname, port, NULL)) {
*waitp = TRUE; /* please wait for the response */
return NULL;
}
/* fall-back to blocking version */
infof(data, "init_resolve_thread() failed for %s; code %lu\n",
hostname, GetLastError());
h = gethostbyname(hostname);
if (!h) {
infof(data, "gethostbyname(2) failed for %s:%d; %s\n",
hostname, port, Curl_strerror(conn,WSAGetLastError()));
return NULL;
}
return Curl_he2ai(h, port);
}
#endif /* CURLRES_IPV4 */
#ifdef CURLRES_IPV6
/*
* Curl_getaddrinfo() - for Windows threading IPv6 enabled
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
int port,
int *waitp)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
curl_socket_t s;
int pf;
struct SessionHandle *data = conn->data;
*waitp = FALSE; /* default to synch response */
/* see if we have an IPv6 stack */
s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s == CURL_SOCKET_BAD) {
/* 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);
/*
* Check if a more limited name resolve has been requested.
*/
switch(data->set.ip_version) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
case CURL_IPRESOLVE_V6:
pf = PF_INET6;
break;
default:
pf = PF_UNSPEC;
break;
}
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
itoa(port, sbuf, 10);
/* fire up a new resolver thread! */
if (init_resolve_thread(conn, hostname, port, &hints)) {
*waitp = TRUE; /* please wait for the response */
return NULL;
}
/* fall-back to blocking version */
infof(data, "init_resolve_thread() failed for %s; code %lu\n",
hostname, GetLastError());
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {
infof(data, "getaddrinfo() failed for %s:%d; %s\n",
hostname, port, Curl_strerror(conn,WSAGetLastError()));
return NULL;
}
return res;
}
#endif /* CURLRES_IPV6 */
#endif /* CURLRES_THREADED */

1996
Utilities/cmcurl/http.c Normal file

File diff suppressed because it is too large Load Diff

61
Utilities/cmcurl/http.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef __HTTP_H
#define __HTTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef CURL_DISABLE_HTTP
bool Curl_compareheader(char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
const char *content); /* content string to find */
/* ftp can use this as well */
CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
int tunnelsocket,
char *hostname, int remote_port);
/* protocol-specific functions set up to be called by the main engine */
CURLcode Curl_http(struct connectdata *conn);
CURLcode Curl_http_done(struct connectdata *, CURLcode);
CURLcode Curl_http_connect(struct connectdata *conn);
/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn);
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
ssize_t length, ssize_t *wrote);
/* These functions are in http.c */
void Curl_http_auth_stage(struct SessionHandle *data, int stage);
CURLcode Curl_http_input_auth(struct connectdata *conn,
int httpcode, char *header);
CURLcode Curl_http_auth_act(struct connectdata *conn);
int Curl_http_should_fail(struct connectdata *conn);
/* If only the PICKNONE bit is set, there has been a round-trip and we
selected to use no auth at all. Ie, we actively select no auth, as opposed
to not having one selected. The other CURLAUTH_* defines are present in the
public curl/curl.h header. */
#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */
#endif
#endif

View File

@ -0,0 +1,264 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include "urldata.h" /* it includes http_chunks.h */
#include "sendf.h" /* for the client write stuff */
#include "content_encoding.h"
#include "http.h"
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
/*
* Chunk format (simplified):
*
* <HEX SIZE>[ chunk extension ] CRLF
* <DATA> CRLF
*
* Highlights from RFC2616 section 3.6 say:
The chunked encoding modifies the body of a message in order to
transfer it as a series of chunks, each with its own size indicator,
followed by an OPTIONAL trailer containing entity-header fields. This
allows dynamically produced content to be transferred along with the
information necessary for the recipient to verify that it has
received the full message.
Chunked-Body = *chunk
last-chunk
trailer
CRLF
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
The chunk-size field is a string of hex digits indicating the size of
the chunk. The chunked encoding is ended by any chunk whose size is
zero, followed by the trailer, which is terminated by an empty line.
*/
void Curl_httpchunk_init(struct connectdata *conn)
{
struct Curl_chunker *chunk = &conn->proto.http->chunk;
chunk->hexindex=0; /* start at 0 */
chunk->dataleft=0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */
}
/*
* chunk_read() returns a OK for normal operations, or a positive return code
* for errors. STOP means this sequence of chunks is complete. The 'wrote'
* argument is set to tell the caller how many bytes we actually passed to the
* client (for byte-counting and whatever).
*
* The states and the state-machine is further explained in the header file.
*/
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
char *datap,
ssize_t datalen,
ssize_t *wrotep)
{
CURLcode result=CURLE_OK;
struct Curl_chunker *ch = &conn->proto.http->chunk;
struct Curl_transfer_keeper *k = &conn->keep;
size_t piece;
size_t length = (size_t)datalen;
size_t *wrote = (size_t *)wrotep;
*wrote = 0; /* nothing's written yet */
while(length) {
switch(ch->state) {
case CHUNK_HEX:
if(isxdigit((int)*datap)) {
if(ch->hexindex < MAXNUM_SIZE) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
length--;
ch->hexindex++;
}
else {
return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */
}
}
else {
if(0 == ch->hexindex) {
/* This is illegal data, we received junk where we expected
a hexadecimal digit. */
return CHUNKE_ILLEGAL_HEX;
}
/* length and datap are unmodified */
ch->hexbuffer[ch->hexindex]=0;
ch->datasize=strtoul(ch->hexbuffer, NULL, 16);
ch->state = CHUNK_POSTHEX;
}
break;
case CHUNK_POSTHEX:
/* In this state, we're waiting for CRLF to arrive. We support
this to allow so called chunk-extensions to show up here
before the CRLF comes. */
if(*datap == '\r')
ch->state = CHUNK_CR;
length--;
datap++;
break;
case CHUNK_CR:
/* waiting for the LF */
if(*datap == '\n') {
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
ch->state = CHUNK_STOP; /* stop reading! */
if(1 == length) {
/* This was the final byte, return right now */
return CHUNKE_STOP;
}
}
else
ch->state = CHUNK_DATA;
}
else
/* previously we got a fake CR, go back to CR waiting! */
ch->state = CHUNK_CR;
datap++;
length--;
break;
case CHUNK_DATA:
/* we get pure and fine data
We expect another 'datasize' of data. We have 'length' right now,
it can be more or less than 'datasize'. Get the smallest piece.
*/
piece = (ch->datasize >= length)?length:ch->datasize;
/* Write the data portion available */
#ifdef HAVE_LIBZ
switch (conn->keep.content_encoding) {
case IDENTITY:
#endif
if(!k->ignorebody)
result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap,
piece);
#ifdef HAVE_LIBZ
break;
case DEFLATE:
/* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap;
result = Curl_unencode_deflate_write(conn->data, &conn->keep,
(ssize_t)piece);
break;
case GZIP:
/* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap;
result = Curl_unencode_gzip_write(conn->data, &conn->keep,
(ssize_t)piece);
break;
case COMPRESS:
default:
failf (conn->data,
"Unrecognized content encoding type. "
"libcurl understands `identity', `deflate' and `gzip' "
"content encodings.");
return CHUNKE_BAD_ENCODING;
}
#endif
if(result)
return CHUNKE_WRITE_ERROR;
*wrote += piece;
ch->datasize -= piece; /* decrease amount left to expect */
datap += piece; /* move read pointer forward */
length -= piece; /* decrease space left in this round */
if(0 == ch->datasize)
/* end of data this round, we now expect a trailing CRLF */
ch->state = CHUNK_POSTCR;
break;
case CHUNK_POSTCR:
if(*datap == '\r') {
ch->state = CHUNK_POSTLF;
datap++;
length--;
}
else
return CHUNKE_BAD_CHUNK;
break;
case CHUNK_POSTLF:
if(*datap == '\n') {
/*
* The last one before we go back to hex state and start all
* over.
*/
Curl_httpchunk_init(conn);
datap++;
length--;
}
else
return CHUNKE_BAD_CHUNK;
break;
case CHUNK_STOP:
/* If we arrive here, there is data left in the end of the buffer
even if there's no more chunks to read */
ch->dataleft = length;
return CHUNKE_STOP; /* return stop */
default:
return CHUNKE_STATE_ERROR;
}
}
return CHUNKE_OK;
}
#endif /* CURL_DISABLE_HTTP */

View File

@ -0,0 +1,88 @@
#ifndef __HTTP_CHUNKS_H
#define __HTTP_CHUNKS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/*
* The longest possible hexadecimal number we support in a chunked transfer.
* Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul()
* to convert it, we "only" support 2^32 bytes chunk data.
*/
#define MAXNUM_SIZE 16
typedef enum {
CHUNK_FIRST, /* never use */
/* In this we await and buffer all hexadecimal digits until we get one
that isn't a hexadecimal digit. When done, we go POSTHEX */
CHUNK_HEX,
/* We have received the hexadecimal digit and we eat all characters until
we get a CRLF pair. When we see a CR we go to the CR state. */
CHUNK_POSTHEX,
/* A single CR has been found and we should get a LF right away in this
state or we go back to POSTHEX. When LF is received, we go to DATA.
If the size given was zero, we set state to STOP and return. */
CHUNK_CR,
/* We eat the amount of data specified. When done, we move on to the
POST_CR state. */
CHUNK_DATA,
/* POSTCR should get a CR and nothing else, then move to POSTLF */
CHUNK_POSTCR,
/* POSTLF should get a LF and nothing else, then move back to HEX as
the CRLF combination marks the end of a chunk */
CHUNK_POSTLF,
/* This is mainly used to really mark that we're out of the game.
NOTE: that there's a 'dataleft' field in the struct that will tell how
many bytes that were not passed to the client in the end of the last
buffer! */
CHUNK_STOP,
CHUNK_LAST /* never use */
} ChunkyState;
typedef enum {
CHUNKE_STOP = -1,
CHUNKE_OK = 0,
CHUNKE_TOO_LONG_HEX = 1,
CHUNKE_ILLEGAL_HEX,
CHUNKE_BAD_CHUNK,
CHUNKE_WRITE_ERROR,
CHUNKE_STATE_ERROR,
CHUNKE_BAD_ENCODING,
CHUNKE_LAST
} CHUNKcode;
struct Curl_chunker {
char hexbuffer[ MAXNUM_SIZE + 1];
int hexindex;
ChunkyState state;
size_t datasize;
size_t dataleft; /* untouched data amount at the end of the last buffer */
};
#endif

View File

@ -0,0 +1,482 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "base64.h"
#include "md5.h"
#include "http_digest.h"
#include "strtok.h"
#include "url.h" /* for Curl_safefree() */
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
/* Test example headers:
WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
Proxy-Authenticate: Digest realm="testrealm", nonce="1053604598"
*/
CURLdigest Curl_input_digest(struct connectdata *conn,
bool proxy,
char *header) /* rest of the *-authenticate:
header */
{
bool more = TRUE;
char *token;
char *tmp;
bool foundAuth = FALSE;
bool foundAuthInt = FALSE;
struct SessionHandle *data=conn->data;
bool before = FALSE; /* got a nonce before */
struct digestdata *d;
if(proxy) {
d = &data->state.proxydigest;
}
else {
d = &data->state.digest;
}
/* skip initial whitespaces */
while(*header && isspace((int)*header))
header++;
if(checkprefix("Digest", header)) {
header += strlen("Digest");
/* If we already have received a nonce, keep that in mind */
if(d->nonce)
before = TRUE;
/* clear off any former leftovers and init to defaults */
Curl_digest_cleanup_one(d);
while(more) {
char value[32];
char content[128];
size_t totlen;
while(*header && isspace((int)*header))
header++;
/* how big can these strings be? */
if((2 == sscanf(header, "%31[^=]=\"%127[^\"]\"",
value, content)) ||
/* try the same scan but without quotes around the content but don't
include the possibly trailing comma */
(2 == sscanf(header, "%31[^=]=%127[^,]",
value, content)) ) {
if(strequal(value, "nonce")) {
d->nonce = strdup(content);
if(!d->nonce)
return CURLDIGEST_NOMEM;
}
else if(strequal(value, "stale")) {
if(strequal(content, "true")) {
d->stale = TRUE;
d->nc = 1; /* we make a new nonce now */
}
}
else if(strequal(value, "realm")) {
d->realm = strdup(content);
if(!d->realm)
return CURLDIGEST_NOMEM;
}
else if(strequal(value, "opaque")) {
d->opaque = strdup(content);
if(!d->opaque)
return CURLDIGEST_NOMEM;
}
else if(strequal(value, "qop")) {
char *tok_buf;
/* tokenize the list and choose auth if possible, use a temporary
clone of the buffer since strtok_r() ruins it */
tmp = strdup(content);
if(!tmp)
return CURLDIGEST_NOMEM;
token = strtok_r(tmp, ",", &tok_buf);
while (token != NULL) {
if (strequal(token, "auth")) {
foundAuth = TRUE;
}
else if (strequal(token, "auth-int")) {
foundAuthInt = TRUE;
}
token = strtok_r(NULL, ",", &tok_buf);
}
free(tmp);
/*select only auth o auth-int. Otherwise, ignore*/
if (foundAuth) {
d->qop = strdup("auth");
if(!d->qop)
return CURLDIGEST_NOMEM;
}
else if (foundAuthInt) {
d->qop = strdup("auth-int");
if(!d->qop)
return CURLDIGEST_NOMEM;
}
}
else if(strequal(value, "algorithm")) {
d->algorithm = strdup(content);
if(!d->algorithm)
return CURLDIGEST_NOMEM;
if(strequal(content, "MD5-sess"))
d->algo = CURLDIGESTALGO_MD5SESS;
else if(strequal(content, "MD5"))
d->algo = CURLDIGESTALGO_MD5;
else
return CURLDIGEST_BADALGO;
}
else {
/* unknown specifier, ignore it! */
}
totlen = strlen(value)+strlen(content)+1;
if(header[strlen(value)+1] == '\"')
/* the contents were within quotes, then add 2 for them to the
length */
totlen += 2;
}
else
break; /* we're done here */
header += totlen;
if(',' == *header)
/* allow the list to be comma-separated */
header++;
}
/* We had a nonce since before, and we got another one now without
'stale=true'. This means we provided bad credentials in the previous
request */
if(before && !d->stale)
return CURLDIGEST_BAD;
/* We got this header without a nonce, that's a bad Digest line! */
if(!d->nonce)
return CURLDIGEST_BAD;
}
else
/* else not a digest, get out */
return CURLDIGEST_NONE;
return CURLDIGEST_FINE;
}
/* convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
static void md5_to_ascii(unsigned char *source, /* 16 bytes */
unsigned char *dest) /* 33 bytes */
{
int i;
for(i=0; i<16; i++)
snprintf((char *)&dest[i*2], 3, "%02x", source[i]);
}
CURLcode Curl_output_digest(struct connectdata *conn,
bool proxy,
unsigned char *request,
unsigned char *uripath)
{
/* We have a Digest setup for this, use it! Now, to get all the details for
this sorted out, I must urge you dear friend to read up on the RFC2617
section 3.2.2, */
unsigned char md5buf[16]; /* 16 bytes/128 bits */
unsigned char request_digest[33];
unsigned char *md5this;
unsigned char *ha1;
unsigned char ha2[33];/* 32 digits and 1 zero byte */
char cnoncebuf[7];
char *cnonce;
char *tmp;
struct timeval now;
char **allocuserpwd;
char *userp;
char *passwdp;
struct auth *authp;
struct SessionHandle *data = conn->data;
struct digestdata *d;
if(proxy) {
d = &data->state.proxydigest;
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->proxyuser;
passwdp = conn->proxypasswd;
authp = &data->state.authproxy;
}
else {
d = &data->state.digest;
allocuserpwd = &conn->allocptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
authp = &data->state.authhost;
}
/* not set means empty */
if(!userp)
userp=(char *)"";
if(!passwdp)
passwdp=(char *)"";
if(!d->nonce) {
authp->done = FALSE;
return CURLE_OK;
}
authp->done = TRUE;
if(!d->nc)
d->nc = 1;
if(!d->cnonce) {
/* Generate a cnonce */
now = Curl_tvnow();
snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", now.tv_sec);
if(Curl_base64_encode(cnoncebuf, strlen(cnoncebuf), &cnonce))
d->cnonce = cnonce;
else
return CURLE_OUT_OF_MEMORY;
}
/*
if the algorithm is "MD5" or unspecified (which then defaults to MD5):
A1 = unq(username-value) ":" unq(realm-value) ":" passwd
if the algorithm is "MD5-sess" then:
A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
":" unq(nonce-value) ":" unq(cnonce-value)
*/
md5this = (unsigned char *)
aprintf("%s:%s:%s", userp, d->realm, passwdp);
if(!md5this)
return CURLE_OUT_OF_MEMORY;
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
ha1 = (unsigned char *)malloc(33); /* 32 digits and 1 zero byte */
if(!ha1)
return CURLE_OUT_OF_MEMORY;
md5_to_ascii(md5buf, ha1);
if(d->algo == CURLDIGESTALGO_MD5SESS) {
/* nonce and cnonce are OUTSIDE the hash */
tmp = aprintf("%s:%s:%s", ha1, d->nonce, d->cnonce);
free(ha1);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
ha1 = (unsigned char *)tmp;
}
/*
If the "qop" directive's value is "auth" or is unspecified, then A2 is:
A2 = Method ":" digest-uri-value
If the "qop" value is "auth-int", then A2 is:
A2 = Method ":" digest-uri-value ":" H(entity-body)
(The "Method" value is the HTTP request method as specified in section
5.1.1 of RFC 2616)
*/
md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
if(!md5this) {
free(ha1);
return CURLE_OUT_OF_MEMORY;
}
if (d->qop && strequal(d->qop, "auth-int")) {
/* We don't support auth-int at the moment. I can't see a easy way to get
entity-body here */
/* TODO: Append H(entity-body)*/
}
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, ha2);
if (d->qop) {
md5this = (unsigned char *)aprintf("%s:%s:%08x:%s:%s:%s",
ha1,
d->nonce,
d->nc,
d->cnonce,
d->qop,
ha2);
}
else {
md5this = (unsigned char *)aprintf("%s:%s:%s",
ha1,
d->nonce,
ha2);
}
free(ha1);
if(!md5this)
return CURLE_OUT_OF_MEMORY;
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, request_digest);
/* for test case 64 (snooped from a Mozilla 1.3a request)
Authorization: Digest username="testuser", realm="testrealm", \
nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
*/
Curl_safefree(*allocuserpwd);
if (d->qop) {
*allocuserpwd =
aprintf( "%sAuthorization: Digest "
"username=\"%s\", "
"realm=\"%s\", "
"nonce=\"%s\", "
"uri=\"%s\", "
"cnonce=\"%s\", "
"nc=%08x, "
"qop=\"%s\", "
"response=\"%s\"",
proxy?"Proxy-":"",
userp,
d->realm,
d->nonce,
uripath, /* this is the PATH part of the URL */
d->cnonce,
d->nc,
d->qop,
request_digest);
if(strequal(d->qop, "auth"))
d->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0 padded
which tells to the server how many times you are using the
same nonce in the qop=auth mode. */
}
else {
*allocuserpwd =
aprintf( "%sAuthorization: Digest "
"username=\"%s\", "
"realm=\"%s\", "
"nonce=\"%s\", "
"uri=\"%s\", "
"response=\"%s\"",
proxy?"Proxy-":"",
userp,
d->realm,
d->nonce,
uripath, /* this is the PATH part of the URL */
request_digest);
}
if(!*allocuserpwd)
return CURLE_OUT_OF_MEMORY;
/* Add optional fields */
if(d->opaque) {
/* append opaque */
tmp = aprintf("%s, opaque=\"%s\"", *allocuserpwd, d->opaque);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
free(*allocuserpwd);
*allocuserpwd = tmp;
}
if(d->algorithm) {
/* append algorithm */
tmp = aprintf("%s, algorithm=\"%s\"", *allocuserpwd, d->algorithm);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
free(*allocuserpwd);
*allocuserpwd = tmp;
}
/* append CRLF to the userpwd header */
tmp = (char*) realloc(*allocuserpwd, strlen(*allocuserpwd) + 3 + 1);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
strcat(tmp, "\r\n");
*allocuserpwd = tmp;
return CURLE_OK;
}
void Curl_digest_cleanup_one(struct digestdata *d)
{
if(d->nonce)
free(d->nonce);
d->nonce = NULL;
if(d->cnonce)
free(d->cnonce);
d->cnonce = NULL;
if(d->realm)
free(d->realm);
d->realm = NULL;
if(d->opaque)
free(d->opaque);
d->opaque = NULL;
if(d->qop)
free(d->qop);
d->qop = NULL;
if(d->algorithm)
free(d->algorithm);
d->algorithm = NULL;
d->nc = 0;
d->algo = CURLDIGESTALGO_MD5; /* default algorithm */
d->stale = FALSE; /* default means normal, not stale */
}
void Curl_digest_cleanup(struct SessionHandle *data)
{
Curl_digest_cleanup_one(&data->state.digest);
Curl_digest_cleanup_one(&data->state.proxydigest);
}
#endif

View File

@ -0,0 +1,53 @@
#ifndef __HTTP_DIGEST_H
#define __HTTP_DIGEST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
typedef enum {
CURLDIGEST_NONE, /* not a digest */
CURLDIGEST_BAD, /* a digest, but one we don't like */
CURLDIGEST_BADALGO, /* unsupported algorithm requested */
CURLDIGEST_NOMEM,
CURLDIGEST_FINE, /* a digest we act on */
CURLDIGEST_LAST /* last entry in this enum, don't use */
} CURLdigest;
enum {
CURLDIGESTALGO_MD5,
CURLDIGESTALGO_MD5SESS
};
/* this is for digest header input */
CURLdigest Curl_input_digest(struct connectdata *conn,
bool proxy, char *header);
/* this is for creating digest header output */
CURLcode Curl_output_digest(struct connectdata *conn,
bool proxy,
unsigned char *request,
unsigned char *uripath);
void Curl_digest_cleanup(struct SessionHandle *data);
void Curl_digest_cleanup_one(struct digestdata *dig);
#endif

View File

@ -0,0 +1,332 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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_GSSAPI
#ifdef HAVE_GSSMIT
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
#endif
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "base64.h"
#include "http_negotiate.h"
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
static int
get_gss_name(struct connectdata *conn, gss_name_t *server)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 major_status, minor_status;
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
char name[2048];
const char* service;
/* GSSAPI implementation by Globus (known as GSI) requires the name to be
of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
Change following lines if you want to use GSI */
/* IIS uses the <service>@<fqdn> form but uses 'http' as the service name */
if (neg_ctx->gss)
service = "KHTTP";
else
service = "HTTP";
token.length = strlen(service) + 1 + strlen(conn->host.name) + 1;
if (token.length + 1 > sizeof(name))
return EMSGSIZE;
snprintf(name, sizeof(name), "%s@%s", service, conn->host.name);
token.value = (void *) name;
major_status = gss_import_name(&minor_status,
&token,
GSS_C_NT_HOSTBASED_SERVICE,
server);
return GSS_ERROR(major_status) ? -1 : 0;
}
static void
log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix)
{
OM_uint32 maj_stat, min_stat;
OM_uint32 msg_ctx = 0;
gss_buffer_desc status_string;
char buf[1024];
size_t len;
snprintf(buf, sizeof(buf), "%s", prefix);
len = strlen(buf);
do {
maj_stat = gss_display_status (&min_stat,
error_status,
GSS_C_MECH_CODE,
GSS_C_NO_OID,
&msg_ctx,
&status_string);
if (sizeof(buf) > len + status_string.length + 1) {
snprintf(buf + len, sizeof(buf) - len,
": %s", (char*) status_string.value);
len += status_string.length;
}
gss_release_buffer(&min_stat, &status_string);
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
infof(conn->data, buf);
}
int Curl_input_negotiate(struct connectdata *conn, char *header)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 major_status, minor_status, minor_status2;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
int ret;
size_t len;
bool gss;
const char* protocol;
while(*header && isspace((int)*header))
header++;
if(checkprefix("GSS-Negotiate", header)) {
protocol = "GSS-Negotiate";
gss = TRUE;
}
else if (checkprefix("Negotiate", header)) {
protocol = "Negotiate";
gss = FALSE;
}
else
return -1;
if (neg_ctx->context) {
if (neg_ctx->gss != gss) {
return -1;
}
}
else {
neg_ctx->protocol = protocol;
neg_ctx->gss = gss;
}
if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
/* We finished succesfully our part of authentication, but server
* rejected it (since we're again here). Exit with an error since we
* can't invent anything better */
Curl_cleanup_negotiate(conn->data);
return -1;
}
if (neg_ctx->server_name == NULL &&
(ret = get_gss_name(conn, &neg_ctx->server_name)))
return ret;
header += strlen(neg_ctx->protocol);
while(*header && isspace((int)*header))
header++;
len = strlen(header);
if (len > 0) {
int rawlen;
input_token.length = (len+3)/4 * 3;
input_token.value = malloc(input_token.length);
if (input_token.value == NULL)
return ENOMEM;
rawlen = Curl_base64_decode(header, input_token.value);
if (rawlen < 0)
return -1;
input_token.length = rawlen;
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
if (checkprefix("Negotiate", header)) {
ASN1_OBJECT * object = NULL;
int rc = 1;
unsigned char * spnegoToken = NULL;
size_t spnegoTokenLength = 0;
unsigned char * mechToken = NULL;
size_t mechTokenLength = 0;
spnegoToken = malloc(input_token.length);
if (input_token.value == NULL)
return ENOMEM;
spnegoTokenLength = input_token.length;
object = OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
if (!parseSpnegoTargetToken(spnegoToken,
spnegoTokenLength,
NULL,
NULL,
&mechToken,
&mechTokenLength,
NULL,
NULL)) {
free(spnegoToken);
spnegoToken = NULL;
infof(conn->data, "Parse SPNEGO Target Token failed\n");
}
else {
free(input_token.value);
input_token.value = NULL;
input_token.value = malloc(mechTokenLength);
memcpy(input_token.value, mechToken,mechTokenLength);
input_token.length = mechTokenLength;
free(mechToken);
mechToken = NULL;
infof(conn->data, "Parse SPNEGO Target Token succeded\n");
}
}
#endif
}
major_status = gss_init_sec_context(&minor_status,
GSS_C_NO_CREDENTIAL,
&neg_ctx->context,
neg_ctx->server_name,
GSS_C_NO_OID,
GSS_C_DELEG_FLAG,
0,
GSS_C_NO_CHANNEL_BINDINGS,
&input_token,
NULL,
&output_token,
NULL,
NULL);
if (input_token.length > 0)
gss_release_buffer(&minor_status2, &input_token);
neg_ctx->status = major_status;
if (GSS_ERROR(major_status)) {
/* Curl_cleanup_negotiate(conn->data) ??? */
log_gss_error(conn, minor_status,
(char *)"gss_init_sec_context() failed: ");
return -1;
}
if (output_token.length == 0) {
return -1;
}
neg_ctx->output_token = output_token;
/* conn->bits.close = FALSE; */
return 0;
}
CURLcode Curl_output_negotiate(struct connectdata *conn)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 minor_status;
char *encoded = NULL;
int len;
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
if (checkprefix("Negotiate",neg_ctx->protocol)) {
ASN1_OBJECT * object = NULL;
int rc = 1;
unsigned char * spnegoToken = NULL;
size_t spnegoTokenLength = 0;
unsigned char * responseToken = NULL;
size_t responseTokenLength = 0;
responseToken = malloc(neg_ctx->output_token.length);
if ( responseToken == NULL)
return CURLE_OUT_OF_MEMORY;
memcpy(responseToken, neg_ctx->output_token.value,
neg_ctx->output_token.length);
responseTokenLength = neg_ctx->output_token.length;
object=OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
if (!makeSpnegoInitialToken (object,
responseToken,
responseTokenLength,
&spnegoToken,
&spnegoTokenLength)) {
free(responseToken);
responseToken = NULL;
infof(conn->data, "Make SPNEGO Initial Token failed\n");
}
else {
free(neg_ctx->output_token.value);
responseToken = NULL;
neg_ctx->output_token.value = malloc(spnegoTokenLength);
memcpy(neg_ctx->output_token.value, spnegoToken,spnegoTokenLength);
neg_ctx->output_token.length = spnegoTokenLength;
free(spnegoToken);
spnegoToken = NULL;
infof(conn->data, "Make SPNEGO Initial Token succeded\n");
}
}
#endif
len = Curl_base64_encode(neg_ctx->output_token.value,
neg_ctx->output_token.length,
&encoded);
if (len < 0)
return CURLE_OUT_OF_MEMORY;
conn->allocptr.userpwd =
aprintf("Authorization: %s %s\r\n", neg_ctx->protocol, encoded);
free(encoded);
gss_release_buffer(&minor_status, &neg_ctx->output_token);
return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
}
void Curl_cleanup_negotiate(struct SessionHandle *data)
{
OM_uint32 minor_status;
struct negotiatedata *neg_ctx = &data->state.negotiate;
if (neg_ctx->context != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
if (neg_ctx->output_token.length != 0)
gss_release_buffer(&minor_status, &neg_ctx->output_token);
if (neg_ctx->server_name != GSS_C_NO_NAME)
gss_release_name(&minor_status, &neg_ctx->server_name);
memset(neg_ctx, 0, sizeof(*neg_ctx));
}
#endif
#endif

View File

@ -0,0 +1,39 @@
#ifndef __HTTP_NEGOTIATE_H
#define __HTTP_NEGOTIATE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifdef HAVE_GSSAPI
/* this is for Negotiate header input */
int Curl_input_negotiate(struct connectdata *conn, char *header);
/* this is for creating Negotiate header output */
CURLcode Curl_output_negotiate(struct connectdata *conn);
void Curl_cleanup_negotiate(struct SessionHandle *data);
#endif
#endif

View File

@ -0,0 +1,585 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
/* NTLM details:
http://davenport.sourceforge.net/ntlm.html
http://www.innovation.ch/java/ntlm.html
*/
#ifndef CURL_DISABLE_HTTP
#ifdef USE_SSLEAY
/* We need OpenSSL for the crypto lib to provide us with MD4 and DES */
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "base64.h"
#include "http_ntlm.h"
#include "url.h"
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/ssl.h>
#if OPENSSL_VERSION_NUMBER < 0x00907001L
#define DES_key_schedule des_key_schedule
#define DES_cblock des_cblock
#define DES_set_odd_parity des_set_odd_parity
#define DES_set_key des_set_key
#define DES_ecb_encrypt des_ecb_encrypt
/* This is how things were done in the old days */
#define DESKEY(x) x
#define DESKEYARG(x) x
#else
/* Modern version */
#define DESKEYARG(x) *x
#define DESKEY(x) &x
#endif
/* The last #include file should be: */
#include "memdebug.h"
/* Define this to make the type-3 message include the NT response message */
#define USE_NTRESPONSES 1
/*
(*) = A "security buffer" is a triplet consisting of two shorts and one
long:
1. a 'short' containing the length of the buffer in bytes
2. a 'short' containing the allocated space for the buffer in bytes
3. a 'long' containing the offset to the start of the buffer from the
beginning of the NTLM message, in bytes.
*/
CURLntlm Curl_input_ntlm(struct connectdata *conn,
bool proxy, /* if proxy or not */
char *header) /* rest of the www-authenticate:
header */
{
/* point to the correct struct with this */
struct ntlmdata *ntlm;
ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
/* skip initial whitespaces */
while(*header && isspace((int)*header))
header++;
if(checkprefix("NTLM", header)) {
unsigned char buffer[256];
header += strlen("NTLM");
while(*header && isspace((int)*header))
header++;
if(*header) {
/* We got a type-2 message here:
Index Description Content
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
(0x4e544c4d53535000)
8 NTLM Message Type long (0x02000000)
12 Target Name security buffer(*)
20 Flags long
24 Challenge 8 bytes
(32) Context (optional) 8 bytes (two consecutive longs)
(40) Target Information (optional) security buffer(*)
32 (48) start of data block
*/
size_t size = Curl_base64_decode(header, (char *)buffer);
ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
if(size >= 48)
/* the nonce of interest is index [24 .. 31], 8 bytes */
memcpy(ntlm->nonce, &buffer[24], 8);
/* at index decimal 20, there's a 32bit NTLM flag field */
}
else {
if(ntlm->state >= NTLMSTATE_TYPE1)
return CURLNTLM_BAD;
ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
}
}
return CURLNTLM_FINE;
}
/*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
* key schedule ks is also set.
*/
static void setup_des_key(unsigned char *key_56,
DES_key_schedule DESKEYARG(ks))
{
DES_cblock key;
key[0] = key_56[0];
key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
key[7] = (key_56[6] << 1) & 0xFF;
DES_set_odd_parity(&key);
DES_set_key(&key, ks);
}
/*
* takes a 21 byte array and treats it as 3 56-bit DES keys. The
* 8 byte plaintext is encrypted with each key and the resulting 24
* bytes are stored in the results array.
*/
static void calc_resp(unsigned char *keys,
unsigned char *plaintext,
unsigned char *results)
{
DES_key_schedule ks;
setup_des_key(keys, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
DESKEY(ks), DES_ENCRYPT);
setup_des_key(keys+7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
DESKEY(ks), DES_ENCRYPT);
setup_des_key(keys+14, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
DESKEY(ks), DES_ENCRYPT);
}
/*
* Set up lanmanager and nt hashed passwords
*/
static void mkhash(char *password,
unsigned char *nonce, /* 8 bytes */
unsigned char *lmresp /* must fit 0x18 bytes */
#ifdef USE_NTRESPONSES
, unsigned char *ntresp /* must fit 0x18 bytes */
#endif
)
{
unsigned char lmbuffer[21];
#ifdef USE_NTRESPONSES
unsigned char ntbuffer[21];
#endif
unsigned char *pw;
static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
};
unsigned int i;
size_t len = strlen(password);
/* make it fit at least 14 bytes */
pw = malloc(len<7?14:len*2);
if(!pw)
return; /* this will lead to a badly generated package */
if (len > 14)
len = 14;
for (i=0; i<len; i++)
pw[i] = toupper(password[i]);
for (; i<14; i++)
pw[i] = 0;
{
/* create LanManager hashed password */
DES_key_schedule ks;
setup_des_key(pw, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
DESKEY(ks), DES_ENCRYPT);
setup_des_key(pw+7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
DESKEY(ks), DES_ENCRYPT);
memset(lmbuffer+16, 0, 5);
}
/* create LM responses */
calc_resp(lmbuffer, nonce, lmresp);
#ifdef USE_NTRESPONSES
{
/* create NT hashed password */
MD4_CTX MD4;
len = strlen(password);
for (i=0; i<len; i++) {
pw[2*i] = password[i];
pw[2*i+1] = 0;
}
MD4_Init(&MD4);
MD4_Update(&MD4, pw, 2*len);
MD4_Final(ntbuffer, &MD4);
memset(ntbuffer+16, 0, 8);
}
calc_resp(ntbuffer, nonce, ntresp);
#endif
free(pw);
}
#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
(((x) >>16)&0xff), ((x)>>24)
/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn,
bool proxy)
{
const char *domain=""; /* empty */
const char *host=""; /* empty */
int domlen=(int)strlen(domain);
int hostlen = (int)strlen(host);
int hostoff; /* host name offset */
int domoff; /* domain name offset */
size_t size;
char *base64=NULL;
unsigned char ntlmbuf[256]; /* enough, unless the host/domain is very long */
/* point to the address of the pointer that holds the string to sent to the
server, which is for a plain host or for a HTTP proxy */
char **allocuserpwd;
/* point to the name and password for this */
char *userp;
char *passwdp;
/* point to the correct struct with this */
struct ntlmdata *ntlm;
struct auth *authp;
curlassert(conn);
curlassert(conn->data);
if(proxy) {
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->proxyuser;
passwdp = conn->proxypasswd;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}
else {
allocuserpwd = &conn->allocptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
ntlm = &conn->ntlm;
authp = &conn->data->state.authhost;
}
authp->done = FALSE;
/* not set means empty */
if(!userp)
userp=(char *)"";
if(!passwdp)
passwdp=(char *)"";
switch(ntlm->state) {
case NTLMSTATE_TYPE1:
default: /* for the weird cases we (re)start here */
hostoff = 32;
domoff = hostoff + hostlen;
/* Create and send a type-1 message:
Index Description Content
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
(0x4e544c4d53535000)
8 NTLM Message Type long (0x01000000)
12 Flags long
16 Supplied Domain security buffer(*)
24 Supplied Workstation security buffer(*)
32 start of data block
*/
snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
"\x01%c%c%c" /* 32-bit type = 1 */
"%c%c%c%c" /* 32-bit NTLM flag field */
"%c%c" /* domain length */
"%c%c" /* domain allocated space */
"%c%c" /* domain name offset */
"%c%c" /* 2 zeroes */
"%c%c" /* host length */
"%c%c" /* host allocated space */
"%c%c" /* host name offset */
"%c%c" /* 2 zeroes */
"%s" /* host name */
"%s", /* domain string */
0, /* trailing zero */
0,0,0, /* part of type-1 long */
LONGQUARTET(
NTLMFLAG_NEGOTIATE_OEM| /* 2 */
NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
/* equals 0x0202 */
),
SHORTPAIR(domlen),
SHORTPAIR(domlen),
SHORTPAIR(domoff),
0,0,
SHORTPAIR(hostlen),
SHORTPAIR(hostlen),
SHORTPAIR(hostoff),
0,0,
host, domain);
/* initial packet length */
size = 32 + hostlen + domlen;
/* now keeper of the base64 encoded package size */
size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
if(size >0 ) {
Curl_safefree(*allocuserpwd);
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
proxy?"Proxy-":"",
base64);
free(base64);
}
else
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
break;
case NTLMSTATE_TYPE2:
/* We received the type-2 already, create a type-3 message:
Index Description Content
0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
(0x4e544c4d53535000)
8 NTLM Message Type long (0x03000000)
12 LM/LMv2 Response security buffer(*)
20 NTLM/NTLMv2 Response security buffer(*)
28 Domain Name security buffer(*)
36 User Name security buffer(*)
44 Workstation Name security buffer(*)
(52) Session Key (optional) security buffer(*)
(60) Flags (optional) long
52 (64) start of data block
*/
{
int lmrespoff;
int ntrespoff;
int useroff;
unsigned char lmresp[0x18]; /* fixed-size */
#ifdef USE_NTRESPONSES
unsigned char ntresp[0x18]; /* fixed-size */
#endif
const char *user;
int userlen;
user = strchr(userp, '\\');
if(!user)
user = strchr(userp, '/');
if (user) {
domain = userp;
domlen = (int)(user - domain);
user++;
}
else
user = userp;
userlen = (int)strlen(user);
mkhash(passwdp, &ntlm->nonce[0], lmresp
#ifdef USE_NTRESPONSES
, ntresp
#endif
);
domoff = 64; /* always */
useroff = domoff + domlen;
hostoff = useroff + userlen;
lmrespoff = hostoff + hostlen;
ntrespoff = lmrespoff + 0x18;
/* Create the big type-3 message binary blob */
size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
"NTLMSSP%c"
"\x03%c%c%c" /* type-3, 32 bits */
"%c%c%c%c" /* LanManager length + allocated space */
"%c%c" /* LanManager offset */
"%c%c" /* 2 zeroes */
"%c%c" /* NT-response length */
"%c%c" /* NT-response allocated space */
"%c%c" /* NT-response offset */
"%c%c" /* 2 zeroes */
"%c%c" /* domain length */
"%c%c" /* domain allocated space */
"%c%c" /* domain name offset */
"%c%c" /* 2 zeroes */
"%c%c" /* user length */
"%c%c" /* user allocated space */
"%c%c" /* user offset */
"%c%c" /* 2 zeroes */
"%c%c" /* host length */
"%c%c" /* host allocated space */
"%c%c" /* host offset */
"%c%c%c%c%c%c" /* 6 zeroes */
"\xff\xff" /* message length */
"%c%c" /* 2 zeroes */
"\x01\x82" /* flags */
"%c%c" /* 2 zeroes */
/* domain string */
/* user string */
/* host string */
/* LanManager response */
/* NT response */
,
0, /* zero termination */
0,0,0, /* type-3 long, the 24 upper bits */
SHORTPAIR(0x18), /* LanManager response length, twice */
SHORTPAIR(0x18),
SHORTPAIR(lmrespoff),
0x0, 0x0,
#ifdef USE_NTRESPONSES
SHORTPAIR(0x18), /* NT-response length, twice */
SHORTPAIR(0x18),
#else
0x0, 0x0,
0x0, 0x0,
#endif
SHORTPAIR(ntrespoff),
0x0, 0x0,
SHORTPAIR(domlen),
SHORTPAIR(domlen),
SHORTPAIR(domoff),
0x0, 0x0,
SHORTPAIR(userlen),
SHORTPAIR(userlen),
SHORTPAIR(useroff),
0x0, 0x0,
SHORTPAIR(hostlen),
SHORTPAIR(hostlen),
SHORTPAIR(hostoff),
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
0x0, 0x0);
/* size is now 64 */
size=64;
ntlmbuf[62]=ntlmbuf[63]=0;
memcpy(&ntlmbuf[size], domain, domlen);
size += domlen;
memcpy(&ntlmbuf[size], user, userlen);
size += userlen;
/* we append the binary hashes to the end of the blob */
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
memcpy(&ntlmbuf[size], lmresp, 0x18);
size += 0x18;
}
#ifdef USE_NTRESPONSES
if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
memcpy(&ntlmbuf[size], ntresp, 0x18);
size += 0x18;
}
#endif
ntlmbuf[56] = (unsigned char)(size & 0xff);
ntlmbuf[57] = (unsigned char)(size >> 8);
/* convert the binary blob into base64 */
size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
if(size >0 ) {
Curl_safefree(*allocuserpwd);
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
proxy?"Proxy-":"",
base64);
free(base64);
}
else
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
authp->done = TRUE;
}
break;
case NTLMSTATE_TYPE3:
/* connection is already authenticated,
* don't send a header in future requests */
if(*allocuserpwd) {
free(*allocuserpwd);
*allocuserpwd=NULL;
}
authp->done = TRUE;
break;
}
return CURLE_OK;
}
#endif /* USE_SSLEAY */
#endif /* !CURL_DISABLE_HTTP */

View File

@ -0,0 +1,143 @@
#ifndef __HTTP_NTLM_H
#define __HTTP_NTLM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
typedef enum {
CURLNTLM_NONE, /* not a ntlm */
CURLNTLM_BAD, /* an ntlm, but one we don't like */
CURLNTLM_FIRST, /* the first 401-reply we got with NTLM */
CURLNTLM_FINE, /* an ntlm we act on */
CURLNTLM_LAST /* last entry in this enum, don't use */
} CURLntlm;
/* this is for ntlm header input */
CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, char *header);
/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
void Curl_ntlm_cleanup(struct SessionHandle *data);
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
/* Indicates that Unicode strings are supported for use in security buffer
data. */
#define NTLMFLAG_NEGOTIATE_OEM (1<<1)
/* Indicates that OEM strings are supported for use in security buffer data. */
#define NTLMFLAG_REQUEST_TARGET (1<<2)
/* Requests that the server's authentication realm be included in the Type 2
message. */
/* unknown (1<<3) */
#define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
/* Specifies that authenticated communication between the client and server
should carry a digital signature (message integrity). */
#define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
/* Specifies that authenticated communication between the client and server
should be encrypted (message confidentiality). */
#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
/* Indicates that the LAN Manager session key should be used for signing and
sealing authenticated communications. */
#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
/* Indicates that NTLM authentication is being used. */
/* unknown (1<<10) */
/* unknown (1<<11) */
#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
/* Sent by the client in the Type 1 message to indicate that a desired
authentication realm is included in the message. */
#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
/* Sent by the client in the Type 1 message to indicate that the client
workstation's name is included in the message. */
#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
/* Sent by the server to indicate that the server and client are on the same
machine. Implies that the client may use a pre-established local security
context rather than responding to the challenge. */
#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
/* Indicates that authenticated communication between the client and server
should be signed with a "dummy" signature. */
#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a domain. */
#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a server. */
#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a share. Presumably, this is for share-level
authentication. Usage is unclear. */
#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
/* Indicates that the NTLM2 signing and sealing scheme should be used for
protecting authenticated communications. */
#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
/* unknown purpose */
#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
/* unknown purpose */
#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
/* Sent by the server in the Type 2 message to indicate that it is including a
Target Information block in the message. */
/* unknown (1<24) */
/* unknown (1<25) */
/* unknown (1<26) */
/* unknown (1<27) */
/* unknown (1<28) */
#define NTLMFLAG_NEGOTIATE_128 (1<<29)
/* Indicates that 128-bit encryption is supported. */
#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_56 (1<<31)
/* Indicates that 56-bit encryption is supported. */
#endif

142
Utilities/cmcurl/if2ip.c Normal file
View File

@ -0,0 +1,142 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN32__) && \
!defined(__riscos__) && !defined(__INTERIX) && !defined(NETWARE)
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_SYS_TIME_H
/* This must be before net/if.h for AIX 3.2 to enjoy life */
#include <sys/time.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
/* -- if2ip() -- */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#ifdef VMS
#include <inet.h>
#endif
#include "if2ip.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#define SYS_ERROR -1
char *Curl_if2ip(const char *interface, char *buf, int buf_size)
{
int dummy;
char *ip=NULL;
if(!interface)
return NULL;
dummy = socket(AF_INET, SOCK_STREAM, 0);
if (SYS_ERROR == dummy) {
return NULL;
}
else {
struct ifreq req;
size_t len = strlen(interface);
memset(&req, 0, sizeof(req));
if(len >= sizeof(req.ifr_name))
return NULL; /* this can't be a fine interface name */
memcpy(req.ifr_name, interface, len+1);
req.ifr_addr.sa_family = AF_INET;
#ifdef IOCTL_3_ARGS
if (SYS_ERROR == ioctl(dummy, SIOCGIFADDR, &req)) {
#else
if (SYS_ERROR == ioctl(dummy, SIOCGIFADDR, &req, sizeof(req))) {
#endif
sclose(dummy);
return NULL;
}
else {
struct in_addr in;
union {
struct sockaddr_in *sin;
struct sockaddr *s;
} soadd;
soadd.s = &req.ifr_dstaddr;
memcpy(&in, &(soadd.sin->sin_addr.s_addr), sizeof(in));
#if defined(HAVE_INET_NTOA_R)
ip = inet_ntoa_r(in,buf,buf_size);
#else
ip = strncpy(buf,inet_ntoa(in),buf_size);
ip[buf_size - 1] = 0;
#endif
}
sclose(dummy);
}
return ip;
}
/* -- end of if2ip() -- */
#else
char *Curl_if2ip(const char *interface, char *buf, int buf_size)
{
(void) interface;
(void) buf;
(void) buf_size;
return NULL;
}
#endif

69
Utilities/cmcurl/if2ip.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef __IF2IP_H
#define __IF2IP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN32__) && \
!defined(__riscos__) && !defined(__INTERIX)
extern char *Curl_if2ip(const char *interface, char *buf, int buf_size);
#else
#define Curl_if2ip(a,b,c) NULL
#endif
#ifdef __INTERIX
/* Nedelcho Stanev's work-around for SFU 3.0 */
struct ifreq {
#define IFNAMSIZ 16
#define IFHWADDRLEN 6
union {
char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
} ifr_ifrn;
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_metric;
int ifru_mtu;
} ifr_ifru;
};
/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the
C code. */
#define ifr_dstaddr ifr_addr
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
#define ifr_metric ifr_ifru.ifru_metric /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
#endif /* interix */
#endif

View File

@ -0,0 +1,9 @@
#ifndef __INET_NTOA_R_H
#define __INET_NTOA_R_H
/*
* My solaris 5.6 system running gcc 2.8.1 does *not* have this prototype
* in any system include file! Isn't that weird?
*/
char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen);
#endif

View File

@ -0,0 +1,204 @@
/*
* Original code by Paul Vixie. "curlified" by Gisle Vanem.
*/
#include "setup.h"
#ifndef HAVE_INET_NTOP
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <string.h>
#include <errno.h>
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "inet_ntop.h"
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
/* this platform has a inet_ntoa_r() function, but no proto declared anywhere
so we include our own proto to make compilers happy */
#include "inet_ntoa_r.h"
#endif
#define IN6ADDRSZ 16
#define INADDRSZ 4
#define INT16SZ 2
#ifdef WIN32
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define SET_ERRNO(e) WSASetLastError(errno = (e))
#else
#define SET_ERRNO(e) errno = e
#endif
/*
* Format an IPv4 address, more or less like inet_ntoa().
*
* Returns `dst' (as a const)
* Note:
* - uses no statics
* - takes a u_char* not an in_addr as input
*/
static const char *inet_ntop4 (const u_char *src, char *dst, size_t size)
{
#ifdef HAVE_INET_NTOA_R
return inet_ntoa_r(*(struct in_addr*)src, dst, size);
#else
union {
const u_char* uch;
const struct in_addr* iad;
} srcaddr;
const char *addr;
srcaddr.uch = src;
addr = inet_ntoa(*srcaddr.iad);
if (strlen(addr) >= size)
{
SET_ERRNO(ENOSPC);
return (NULL);
}
return strcpy(dst, addr);
#endif
}
#ifdef ENABLE_IPV6
/*
* Convert IPv6 binary address into presentation (printable) format.
*/
static const char *inet_ntop6 (const u_char *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp [sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
char *tp;
struct {
long base;
long len;
} best, cur;
u_long words [IN6ADDRSZ / INT16SZ];
int i;
/* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, 0, sizeof(words));
for (i = 0; i < IN6ADDRSZ; i++)
words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
if (words[i] == 0)
{
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
}
else if (cur.base != -1)
{
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
best = cur;
if (best.base != -1 && best.len < 2)
best.base = -1;
/* Format the result.
*/
tp = tmp;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
/* Are we inside the best run of 0x00's?
*/
if (best.base != -1 && i >= best.base && i < (best.base + best.len))
{
if (i == best.base)
*tp++ = ':';
continue;
}
/* Are we following an initial run of 0x00s or any real hex?
*/
if (i != 0)
*tp++ = ':';
/* Is this address an encapsulated IPv4?
*/
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
{
if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
{
SET_ERRNO(ENOSPC);
return (NULL);
}
tp += strlen(tp);
break;
}
tp += snprintf(tp, 5, "%lx", words[i]);
}
/* Was it a trailing run of 0x00's?
*/
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size)
{
SET_ERRNO(ENOSPC);
return (NULL);
}
return strcpy (dst, tmp);
}
#endif /* ENABLE_IPV6 */
/*
* Convert a network format address to presentation format.
*
* Returns pointer to presentation format address (`dst'),
* Returns NULL on error (see errno).
*/
const char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
{
switch (af) {
case AF_INET:
return inet_ntop4((const u_char*)src, buf, size);
#ifdef ENABLE_IPV6
case AF_INET6:
return inet_ntop6((const u_char*)src, buf, size);
#endif
default:
SET_ERRNO(EAFNOSUPPORT);
return NULL;
}
}
#endif /* HAVE_INET_NTOP */

View File

@ -0,0 +1,37 @@
#ifndef __INET_NTOP_H
#define __INET_NTOP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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_INET_NTOP
#define Curl_inet_ntop(af,addr,buf,size) inet_ntop(af,addr,buf,size)
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#else
const char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
#endif
#endif /* __INET_NTOP_H */

View File

@ -0,0 +1,240 @@
/* This is from the BIND 4.9.4 release, modified to compile by itself */
/* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include "setup.h"
#ifndef HAVE_INET_PTON
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <string.h>
#include <errno.h>
#include "inet_pton.h"
#define IN6ADDRSZ 16
#define INADDRSZ 4
#define INT16SZ 2
#ifdef WIN32
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#endif
/*
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static int inet_pton4(const char *src, unsigned char *dst);
#ifdef ENABLE_IPV6
static int inet_pton6(const char *src, unsigned char *dst);
#endif
/* int
* inet_pton(af, src, dst)
* convert from presentation format (which usually means ASCII printable)
* to network format (which is usually some kind of binary format).
* return:
* 1 if the address was valid for the specified address family
* 0 if the address wasn't valid (`dst' is untouched in this case)
* -1 if some other error occurred (`dst' is untouched in this case, too)
* author:
* Paul Vixie, 1996.
*/
int
Curl_inet_pton(int af, const char *src, void *dst)
{
switch (af) {
case AF_INET:
return (inet_pton4(src, dst));
#ifdef ENABLE_IPV6
#ifndef AF_INET6
#define AF_INET6 AF_MAX+1 /* just to let this compile */
#endif
case AF_INET6:
return (inet_pton6(src, dst));
#endif
default:
errno = EAFNOSUPPORT;
return (-1);
}
/* NOTREACHED */
}
/* int
* inet_pton4(src, dst)
* like inet_aton() but without all the hexadecimal and shorthand.
* return:
* 1 if `src' is a valid dotted quad, else 0.
* notice:
* does not touch `dst' unless it's returning 1.
* author:
* Paul Vixie, 1996.
*/
static int
inet_pton4(const char *src, unsigned char *dst)
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
unsigned char tmp[INADDRSZ], *tp;
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr(digits, ch)) != NULL) {
u_int new = *tp * 10 + (pch - digits);
if (new > 255)
return (0);
*tp = new;
if (! saw_digit) {
if (++octets > 4)
return (0);
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
} else
return (0);
}
if (octets < 4)
return (0);
/* bcopy(tmp, dst, INADDRSZ); */
memcpy(dst, tmp, INADDRSZ);
return (1);
}
#ifdef ENABLE_IPV6
/* int
* inet_pton6(src, dst)
* convert presentation level address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
* notice:
* (1) does not touch `dst' unless it's returning 1.
* (2) :: in a full address is silently ignored.
* credit:
* inspired by Mark Andrews.
* author:
* Paul Vixie, 1996.
*/
static int
inet_pton6(const char *src, unsigned char *dst)
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
u_int val;
memset((tp = tmp), 0, IN6ADDRSZ);
endp = tp + IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonp)
return (0);
colonp = tp;
continue;
}
if (tp + INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0) {
tp += INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
}
if (saw_xdigit) {
if (tp + INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
}
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const int n = tp - colonp;
int i;
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
/* bcopy(tmp, dst, IN6ADDRSZ); */
memcpy(dst, tmp, IN6ADDRSZ);
return (1);
}
#endif /* ENABLE_IPV6 */
#endif /* HAVE_INET_PTON */

View File

@ -0,0 +1,37 @@
#ifndef __INET_PTON_H
#define __INET_PTON_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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_INET_PTON
#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#else
int Curl_inet_pton(int, const char *, void *);
#endif
#endif /* __INET_PTON_H */

408
Utilities/cmcurl/krb4.c Normal file
View File

@ -0,0 +1,408 @@
/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
* use in Curl. His latest changes were done 2000-09-18.
*
* It has since been patched away like a madman by Daniel Stenberg
* <daniel@haxx.se> to make it better applied to curl conditions, and to make
* it not use globals, pollute name space and more. This source code awaits a
* rewrite to work around the paragraph 2 in the BSD licenses as explained
* below.
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. */
#include "setup.h"
#ifndef CURL_DISABLE_FTP
#ifdef HAVE_KRB4
#include "security.h"
#include "base64.h"
#include <stdlib.h>
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <string.h>
#include <krb.h>
#include <des.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for getpid() */
#endif
#include "ftp.h"
#include "sendf.h"
#include "krb4.h"
#include "curl_memory.h"
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
/* The last #include file should be: */
#include "memdebug.h"
#define LOCAL_ADDR (&conn->local_addr)
#define REMOTE_ADDR conn->ip_addr->ai_addr
#define myctladdr LOCAL_ADDR
#define hisctladdr REMOTE_ADDR
struct krb4_data {
des_cblock key;
des_key_schedule schedule;
char name[ANAME_SZ];
char instance[INST_SZ];
char realm[REALM_SZ];
};
#ifndef HAVE_STRLCPY
/* if it ever goes non-static, make it Curl_ prefixed! */
static size_t
strlcpy (char *dst, const char *src, size_t dst_sz)
{
size_t n;
char *p;
for (p = dst, n = 0;
n + 1 < dst_sz && *src != '\0';
++p, ++src, ++n)
*p = *src;
*p = '\0';
if (*src == '\0')
return n;
else
return n + strlen (src);
}
#else
size_t strlcpy (char *dst, const char *src, size_t dst_sz);
#endif
static int
krb4_check_prot(void *app_data, int level)
{
app_data = NULL; /* prevent compiler warning */
if(level == prot_confidential)
return -1;
return 0;
}
static int
krb4_decode(void *app_data, void *buf, int len, int level,
struct connectdata *conn)
{
MSG_DAT m;
int e;
struct krb4_data *d = app_data;
if(level == prot_safe)
e = krb_rd_safe(buf, len, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
else
e = krb_rd_priv(buf, len, d->schedule, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
if(e) {
struct SessionHandle *data = conn->data;
infof(data, "krb4_decode: %s\n", krb_get_err_text(e));
return -1;
}
memmove(buf, m.app_data, m.app_length);
return m.app_length;
}
static int
krb4_overhead(void *app_data, int level, int len)
{
/* no arguments are used, just init them to prevent compiler warnings */
app_data = NULL;
level = 0;
len = 0;
return 31;
}
static int
krb4_encode(void *app_data, void *from, int length, int level, void **to,
struct connectdata *conn)
{
struct krb4_data *d = app_data;
*to = malloc(length + 31);
if(level == prot_safe)
return krb_mk_safe(from, *to, length, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else if(level == prot_private)
return krb_mk_priv(from, *to, length, d->schedule, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else
return -1;
}
static int
mk_auth(struct krb4_data *d, KTEXT adat,
const char *service, char *host, int checksum)
{
int ret;
CREDENTIALS cred;
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_mk_req(adat, sname, inst, realm, checksum);
if(ret)
return ret;
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_get_cred(sname, inst, realm, &cred);
memmove(&d->key, &cred.session, sizeof(des_cblock));
des_key_sched(&d->key, d->schedule);
memset(&cred, 0, sizeof(cred));
return ret;
}
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
int krb_get_our_ip_for_realm(char *, struct in_addr *);
#endif
static int
krb4_auth(void *app_data, struct connectdata *conn)
{
int ret;
char *p;
int len;
KTEXT_ST adat;
MSG_DAT msg_data;
int checksum;
u_int32_t cs;
struct krb4_data *d = app_data;
char *host = conn->host.name;
ssize_t nread;
int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
CURLcode result;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
perror("getsockname()");
checksum = getpid();
ret = mk_auth(d, &adat, "ftp", host, checksum);
if(ret == KDC_PR_UNKNOWN)
ret = mk_auth(d, &adat, "rcmd", host, checksum);
if(ret) {
Curl_infof(data, "%s\n", krb_get_err_text(ret));
return AUTH_CONTINUE;
}
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
if (krb_get_config_bool("nat_in_use")) {
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
struct in_addr natAddr;
if (krb_get_our_ip_for_realm(krb_realmofhost(host),
&natAddr) != KSUCCESS
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
Curl_infof(data, "Can't get address for realm %s\n",
krb_realmofhost(host));
else {
if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
#ifdef HAVE_INET_NTOA_R
char ntoa_buf[64];
char *ip = (char *)inet_ntoa_r(natAddr, ntoa_buf, sizeof(ntoa_buf));
#else
char *ip = (char *)inet_ntoa(natAddr);
#endif
Curl_infof(data, "Using NAT IP address (%s) for kerberos 4\n", ip);
localaddr->sin_addr = natAddr;
}
}
}
#endif
if(Curl_base64_encode((char *)adat.dat, adat.length, &p) < 1) {
Curl_failf(data, "Out of memory base64-encoding");
return AUTH_CONTINUE;
}
result = Curl_ftpsendf(conn, "ADAT %s", p);
free(p);
if(result)
return -2;
if(Curl_GetFTPResponse(&nread, conn, NULL))
return -1;
if(data->state.buffer[0] != '2'){
Curl_failf(data, "Server didn't accept auth data");
return AUTH_ERROR;
}
p = strstr(data->state.buffer, "ADAT=");
if(!p) {
Curl_failf(data, "Remote host didn't send adat reply");
return AUTH_ERROR;
}
p += 5;
len = Curl_base64_decode(p, (char *)adat.dat);
if(len < 0) {
Curl_failf(data, "Failed to decode base64 from server");
return AUTH_ERROR;
}
adat.length = len;
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
(struct sockaddr_in *)hisctladdr,
(struct sockaddr_in *)myctladdr, &msg_data);
if(ret) {
Curl_failf(data, "Error reading reply from server: %s",
krb_get_err_text(ret));
return AUTH_ERROR;
}
krb_get_int(msg_data.app_data, &cs, 4, 0);
if(cs - checksum != 1) {
Curl_failf(data, "Bad checksum returned from server");
return AUTH_ERROR;
}
return AUTH_OK;
}
struct Curl_sec_client_mech Curl_krb4_client_mech = {
"KERBEROS_V4",
sizeof(struct krb4_data),
NULL, /* init */
krb4_auth,
NULL, /* end */
krb4_check_prot,
krb4_overhead,
krb4_encode,
krb4_decode
};
CURLcode Curl_krb_kauth(struct connectdata *conn)
{
des_cblock key;
des_key_schedule schedule;
KTEXT_ST tkt, tktcopy;
char *name;
char *p;
char passwd[100];
int tmp;
ssize_t nread;
int save;
CURLcode result;
save = Curl_set_command_prot(conn, prot_private);
result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user);
if(result)
return result;
result = Curl_GetFTPResponse(&nread, conn, NULL);
if(result)
return result;
if(conn->data->state.buffer[0] != '3'){
Curl_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
p = strstr(conn->data->state.buffer, "T=");
if(!p) {
Curl_failf(conn->data, "Bad reply from server");
Curl_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
p += 2;
tmp = Curl_base64_decode(p, (char *)tkt.dat);
if(tmp < 0) {
Curl_failf(conn->data, "Failed to decode base64 in reply.\n");
Curl_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
tkt.length = tmp;
tktcopy.length = tkt.length;
p = strstr(conn->data->state.buffer, "P=");
if(!p) {
Curl_failf(conn->data, "Bad reply from server");
Curl_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
name = p + 2;
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
*p = 0;
des_string_to_key (conn->passwd, &key);
des_key_sched(&key, schedule);
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
if (strcmp ((char*)tktcopy.dat + 8,
KRB_TICKET_GRANTING_TICKET) != 0) {
afs_string_to_key(passwd,
krb_realmofhost(conn->host.name),
&key);
des_key_sched(&key, schedule);
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
}
memset(key, 0, sizeof(key));
memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd));
if(Curl_base64_encode((char *)tktcopy.dat, tktcopy.length, &p) < 1) {
failf(conn->data, "Out of memory base64-encoding.");
Curl_set_command_prot(conn, save);
return CURLE_OUT_OF_MEMORY;
}
memset (tktcopy.dat, 0, tktcopy.length);
result = Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p);
free(p);
if(result)
return result;
result = Curl_GetFTPResponse(&nread, conn, NULL);
if(result)
return result;
Curl_set_command_prot(conn, save);
return CURLE_OK;
}
#endif /* HAVE_KRB4 */
#endif /* CURL_DISABLE_FTP */

27
Utilities/cmcurl/krb4.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef __KRB4_H
#define __KRB4_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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_krb_kauth(struct connectdata *conn);
#endif

625
Utilities/cmcurl/ldap.c Normal file
View File

@ -0,0 +1,625 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#ifndef CURL_DISABLE_LDAP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#if defined(WIN32)
# include <windows.h>
# include <malloc.h>
# include <WinLdap.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif
#include "urldata.h"
#include <curl/curl.h>
#include "sendf.h"
#include "escape.h"
#include "transfer.h"
#include "strequal.h"
#include "strtok.h"
#include "ldap.h"
#include "curl_memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "memdebug.h"
/* WLdap32.dll functions are *not* stdcall. Must call these via __cdecl
* pointers in case libcurl was compiled as fastcall (-Gr).
*/
#if !defined(WIN32) && !defined(__cdecl)
#define __cdecl
#endif
#ifndef LDAP_SIZELIMIT_EXCEEDED
#define LDAP_SIZELIMIT_EXCEEDED 4
#endif
#define DLOPEN_MODE RTLD_LAZY /*! assume all dlopen() implementations have
this */
#if defined(RTLD_LAZY_GLOBAL) /* It turns out some systems use this: */
# undef DLOPEN_MODE
# define DLOPEN_MODE RTLD_LAZY_GLOBAL
#elif defined(RTLD_GLOBAL)
# undef DLOPEN_MODE
# define DLOPEN_MODE (RTLD_LAZY | RTLD_GLOBAL)
#endif
#define DYNA_GET_FUNCTION(type, fnc) do { \
(fnc) = (type)DynaGetFunction(#fnc); \
if ((fnc) == NULL) \
return CURLE_FUNCTION_NOT_FOUND; \
} while (0)
/*! CygWin etc. configure could set these, but we don't want it.
* Must use WLdap32.dll code.
*/
#if defined(WIN32)
#undef HAVE_DLOPEN
#undef HAVE_LIBDL
#endif
typedef void * (*dynafunc)(void *input);
/***********************************************************************
*/
static void *libldap = NULL;
#ifndef WIN32
static void *liblber = NULL;
#endif
static int DynaOpen(const char **mod_name)
{
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
if (libldap == NULL) {
/*
* libldap.so should be able to resolve its dependency on
* liblber.so automatically, but since it does not we will
* handle it here by opening liblber.so as global.
*/
*mod_name = "liblber.so";
liblber = dlopen(*mod_name, DLOPEN_MODE);
/* Assume loading libldap.so will fail if loading of liblber.so failed
*/
if (liblber) {
*mod_name = "libldap.so";
libldap = dlopen(*mod_name, RTLD_LAZY);
}
}
return (libldap != NULL && liblber != NULL);
#elif defined(WIN32)
*mod_name = "wldap32.dll";
if (!libldap)
libldap = (void*)LoadLibrary(*mod_name);
return (libldap != NULL);
#else
return (0);
#endif
}
static void DynaClose(void)
{
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
if (libldap) {
dlclose(libldap);
libldap=NULL;
}
if (liblber) {
dlclose(liblber);
liblber=NULL;
}
#elif defined(WIN32)
if (libldap) {
FreeLibrary ((HMODULE)libldap);
libldap = NULL;
}
#endif
}
static dynafunc DynaGetFunction(const char *name)
{
dynafunc func = (dynafunc)NULL;
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
if (libldap) {
/* This typecast magic below was brought by Joe Halpin. In ISO C, you
* cannot typecast a data pointer to a function pointer, but that's
* exactly what we need to do here to avoid compiler warnings on picky
* compilers! */
*(void**) (&func) = dlsym(libldap, name);
}
#elif defined(WIN32)
if (libldap) {
func = (dynafunc)GetProcAddress((HINSTANCE)libldap, name);
}
#endif
return func;
}
/***********************************************************************
*/
typedef struct ldap_url_desc {
struct ldap_url_desc *lud_next;
char *lud_scheme;
char *lud_host;
int lud_port;
char *lud_dn;
char **lud_attrs;
int lud_scope;
char *lud_filter;
char **lud_exts;
int lud_crit_exts;
} LDAPURLDesc;
#ifdef WIN32
static int _ldap_url_parse (const struct connectdata *conn,
LDAPURLDesc **ludp);
static void _ldap_free_urldesc (LDAPURLDesc *ludp);
static void (*ldap_free_urldesc)(LDAPURLDesc *) = _ldap_free_urldesc;
#endif
#ifdef DEBUG_LDAP
#define LDAP_TRACE(x) do { \
_ldap_trace ("%u: ", __LINE__); \
_ldap_trace x; \
} while (0)
static void _ldap_trace (const char *fmt, ...);
#else
#define LDAP_TRACE(x) ((void)0)
#endif
CURLcode Curl_ldap(struct connectdata *conn)
{
CURLcode status = CURLE_OK;
int rc = 0;
#ifndef WIN32
int (*ldap_url_parse)(char *, LDAPURLDesc **);
void (*ldap_free_urldesc)(void *);
#endif
void *(__cdecl *ldap_init)(char *, int);
int (__cdecl *ldap_simple_bind_s)(void *, char *, char *);
int (__cdecl *ldap_unbind_s)(void *);
int (__cdecl *ldap_search_s)(void *, char *, int, char *, char **,
int, void **);
void *(__cdecl *ldap_first_entry)(void *, void *);
void *(__cdecl *ldap_next_entry)(void *, void *);
char *(__cdecl *ldap_err2string)(int);
char *(__cdecl *ldap_get_dn)(void *, void *);
char *(__cdecl *ldap_first_attribute)(void *, void *, void **);
char *(__cdecl *ldap_next_attribute)(void *, void *, void *);
char **(__cdecl *ldap_get_values)(void *, void *, const char *);
void (__cdecl *ldap_value_free)(char **);
void (__cdecl *ldap_memfree)(void *);
void (__cdecl *ber_free)(void *, int);
void *server;
LDAPURLDesc *ludp = NULL;
const char *mod_name;
void *result;
void *entryIterator; /*! type should be 'LDAPMessage *' */
int num = 0;
struct SessionHandle *data=conn->data;
infof(data, "LDAP local: %s\n", data->change.url);
if (!DynaOpen(&mod_name)) {
failf(data, "The %s LDAP library/libraries couldn't be opened", mod_name);
return CURLE_LIBRARY_NOT_FOUND;
}
/* The types are needed because ANSI C distinguishes between
* pointer-to-object (data) and pointer-to-function.
*/
DYNA_GET_FUNCTION(void *(*)(char *, int), ldap_init);
DYNA_GET_FUNCTION(int (*)(void *, char *, char *), ldap_simple_bind_s);
DYNA_GET_FUNCTION(int (*)(void *), ldap_unbind_s);
#ifndef WIN32
DYNA_GET_FUNCTION(int (*)(char *, LDAPURLDesc **), ldap_url_parse);
DYNA_GET_FUNCTION(void (*)(void *), ldap_free_urldesc);
#endif
DYNA_GET_FUNCTION(int (*)(void *, char *, int, char *, char **, int,
void **), ldap_search_s);
DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_first_entry);
DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_next_entry);
DYNA_GET_FUNCTION(char *(*)(int), ldap_err2string);
DYNA_GET_FUNCTION(char *(*)(void *, void *), ldap_get_dn);
DYNA_GET_FUNCTION(char *(*)(void *, void *, void **), ldap_first_attribute);
DYNA_GET_FUNCTION(char *(*)(void *, void *, void *), ldap_next_attribute);
DYNA_GET_FUNCTION(char **(*)(void *, void *, const char *), ldap_get_values);
DYNA_GET_FUNCTION(void (*)(char **), ldap_value_free);
DYNA_GET_FUNCTION(void (*)(void *), ldap_memfree);
DYNA_GET_FUNCTION(void (*)(void *, int), ber_free);
server = (*ldap_init)(conn->host.name, (int)conn->port);
if (server == NULL) {
failf(data, "LDAP local: Cannot connect to %s:%d",
conn->host.name, conn->port);
status = CURLE_COULDNT_CONNECT;
goto quit;
}
rc = (*ldap_simple_bind_s)(server,
conn->bits.user_passwd ? conn->user : NULL,
conn->bits.user_passwd ? conn->passwd : NULL);
if (rc != 0) {
failf(data, "LDAP local: %s", (*ldap_err2string)(rc));
status = CURLE_LDAP_CANNOT_BIND;
goto quit;
}
#ifdef WIN32
rc = _ldap_url_parse(conn, &ludp);
#else
rc = (*ldap_url_parse)(data->change.url, &ludp);
#endif
if (rc != 0) {
failf(data, "LDAP local: %s", (*ldap_err2string)(rc));
status = CURLE_LDAP_INVALID_URL;
goto quit;
}
rc = (*ldap_search_s)(server, ludp->lud_dn, ludp->lud_scope,
ludp->lud_filter, ludp->lud_attrs, 0, &result);
if (rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
failf(data, "LDAP remote: %s", (*ldap_err2string)(rc));
status = CURLE_LDAP_SEARCH_FAILED;
goto quit;
}
for(num = 0, entryIterator = (*ldap_first_entry)(server, result);
entryIterator;
entryIterator = (*ldap_next_entry)(server, entryIterator), num++)
{
void *ber = NULL; /*! is really 'BerElement **' */
void *attribute; /*! suspicious that this isn't 'const' */
char *dn = (*ldap_get_dn)(server, entryIterator);
int i;
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4);
Curl_client_write(data, CLIENTWRITE_BODY, (char *)dn, 0);
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
for (attribute = (*ldap_first_attribute)(server, entryIterator, &ber);
attribute;
attribute = (*ldap_next_attribute)(server, entryIterator, ber))
{
char **vals = (*ldap_get_values)(server, entryIterator, attribute);
if (vals != NULL)
{
for (i = 0; (vals[i] != NULL); i++)
{
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\t", 1);
Curl_client_write(data, CLIENTWRITE_BODY, (char*) attribute, 0);
Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2);
Curl_client_write(data, CLIENTWRITE_BODY, vals[i], 0);
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0);
}
/* Free memory used to store values */
(*ldap_value_free)(vals);
}
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
(*ldap_memfree)(attribute);
(*ldap_memfree)(dn);
}
if (ber)
(*ber_free)(ber, 0);
}
quit:
LDAP_TRACE (("Received %d entries\n", num));
if (rc == LDAP_SIZELIMIT_EXCEEDED)
infof(data, "There are more than %d entries\n", num);
if (ludp)
(*ldap_free_urldesc)(ludp);
if (server)
(*ldap_unbind_s)(server);
DynaClose();
/* no data to transfer */
Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
return status;
}
#ifdef DEBUG_LDAP
static void _ldap_trace (const char *fmt, ...)
{
static int do_trace = -1;
va_list args;
if (do_trace == -1) {
const char *env = getenv("CURL_TRACE");
do_trace = (env && atoi(env) > 0);
}
if (!do_trace)
return;
va_start (args, fmt);
vfprintf (stderr, fmt, args);
va_end (args);
}
#endif
#ifdef WIN32
/*
* Return scope-value for a scope-string.
*/
static int str2scope (const char *p)
{
if (!stricmp(p, "one"))
return LDAP_SCOPE_ONELEVEL;
if (!stricmp(p, "onetree"))
return LDAP_SCOPE_ONELEVEL;
if (!stricmp(p, "base"))
return LDAP_SCOPE_BASE;
if (!stricmp(p, "sub"))
return LDAP_SCOPE_SUBTREE;
if (!stricmp( p, "subtree"))
return LDAP_SCOPE_SUBTREE;
return (-1);
}
/*
* Split 'str' into strings separated by commas.
* Note: res[] points into 'str'.
*/
static char **split_str (char *str)
{
char **res, *lasts, *s;
int i;
for (i = 2, s = strchr(str,','); s; i++)
s = strchr(++s,',');
res = calloc(i, sizeof(char*));
if (!res)
return NULL;
for (i = 0, s = strtok_r(str, ",", &lasts); s;
s = strtok_r(NULL, ",", &lasts), i++)
res[i] = s;
return res;
}
/*
* Unescape the LDAP-URL components
*/
static bool unescape_elements (LDAPURLDesc *ludp)
{
int i;
if (ludp->lud_filter) {
ludp->lud_filter = curl_unescape(ludp->lud_filter, 0);
if (!ludp->lud_filter)
return (FALSE);
}
for (i = 0; ludp->lud_attrs && ludp->lud_attrs[i]; i++) {
ludp->lud_attrs[i] = curl_unescape(ludp->lud_attrs[i], 0);
if (!ludp->lud_attrs[i])
return (FALSE);
}
for (i = 0; ludp->lud_exts && ludp->lud_exts[i]; i++) {
ludp->lud_exts[i] = curl_unescape(ludp->lud_exts[i], 0);
if (!ludp->lud_exts[i])
return (FALSE);
}
if (ludp->lud_dn) {
char *dn = ludp->lud_dn;
char *new_dn = curl_unescape(dn, 0);
free(dn);
if (!new_dn)
return (FALSE);
ludp->lud_dn = new_dn;
}
return (TRUE);
}
/*
* Break apart the pieces of an LDAP URL.
* Syntax:
* ldap://<hostname>:<port>/<base_dn>?<attributes>?<scope>?<filter>?<ext>
*
* <hostname> already known from 'conn->host.name'.
* <port> already known from 'conn->remote_port'.
* extract the rest from 'conn->path+1'. All fields are optional. e.g.
* ldap://<hostname>:<port>/?<attributes>?<scope>?<filter> yields ludp->lud_dn = "".
*
* Ref. http://developer.netscape.com/docs/manuals/dirsdk/csdk30/url.htm#2831915
*/
static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
{
char *p, *q;
int i;
if (!conn->path || conn->path[0] != '/' ||
!checkprefix(conn->protostr, conn->data->change.url))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
ludp->lud_port = conn->remote_port;
ludp->lud_host = conn->host.name;
/* parse DN (Distinguished Name).
*/
ludp->lud_dn = strdup(conn->path+1);
if (!ludp->lud_dn)
return LDAP_NO_MEMORY;
p = strchr(ludp->lud_dn, '?');
LDAP_TRACE (("DN '%.*s'\n", p ? (size_t)(p-ludp->lud_dn) : strlen(ludp->lud_dn),
ludp->lud_dn));
if (!p)
goto success;
*p++ = '\0';
/* parse attributes. skip "??".
*/
q = strchr(p, '?');
if (q)
*q++ = '\0';
if (*p && *p != '?') {
ludp->lud_attrs = split_str(p);
if (!ludp->lud_attrs)
return LDAP_NO_MEMORY;
for (i = 0; ludp->lud_attrs[i]; i++)
LDAP_TRACE (("attr[%d] '%s'\n", i, ludp->lud_attrs[i]));
}
p = q;
if (!p)
goto success;
/* parse scope. skip "??"
*/
q = strchr(p, '?');
if (q)
*q++ = '\0';
if (*p && *p != '?') {
ludp->lud_scope = str2scope(p);
if (ludp->lud_scope == -1)
return LDAP_INVALID_SYNTAX;
LDAP_TRACE (("scope %d\n", ludp->lud_scope));
}
p = q;
if (!p)
goto success;
/* parse filter
*/
q = strchr(p, '?');
if (q)
*q++ = '\0';
if (!*p)
return LDAP_INVALID_SYNTAX;
ludp->lud_filter = p;
LDAP_TRACE (("filter '%s'\n", ludp->lud_filter));
p = q;
if (!p)
goto success;
/* parse extensions
*/
ludp->lud_exts = split_str(p);
if (!ludp->lud_exts)
return LDAP_NO_MEMORY;
for (i = 0; ludp->lud_exts[i]; i++)
LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i]));
success:
if (!unescape_elements(ludp))
return LDAP_NO_MEMORY;
return LDAP_SUCCESS;
}
static int _ldap_url_parse (const struct connectdata *conn,
LDAPURLDesc **ludpp)
{
LDAPURLDesc *ludp = calloc(sizeof(*ludp), 1);
int rc;
*ludpp = NULL;
if (!ludp)
return LDAP_NO_MEMORY;
rc = _ldap_url_parse2 (conn, ludp);
if (rc != LDAP_SUCCESS) {
_ldap_free_urldesc(ludp);
ludp = NULL;
}
*ludpp = ludp;
return (rc);
}
static void _ldap_free_urldesc (LDAPURLDesc *ludp)
{
int i;
if (!ludp)
return;
if (ludp->lud_dn)
free(ludp->lud_dn);
if (ludp->lud_filter)
free(ludp->lud_filter);
if (ludp->lud_attrs) {
for (i = 0; ludp->lud_attrs[i]; i++)
free(ludp->lud_attrs[i]);
free(ludp->lud_attrs);
}
if (ludp->lud_exts) {
for (i = 0; ludp->lud_exts[i]; i++)
free(ludp->lud_exts[i]);
free(ludp->lud_exts);
}
free (ludp);
}
#endif /* WIN32 */
#endif /* CURL_DISABLE_LDAP */

29
Utilities/cmcurl/ldap.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __LDAP_H
#define __LDAP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
#ifndef CURL_DISABLE_LDAP
CURLcode Curl_ldap(struct connectdata *conn);
#endif
#endif /* __LDAP_H */

130
Utilities/cmcurl/llist.c Normal file
View File

@ -0,0 +1,130 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <string.h>
#include <stdlib.h>
#include "llist.h"
#include "curl_memory.h"
/* this must be the last include file */
#include "memdebug.h"
void
Curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
{
l->size = 0;
l->dtor = dtor;
l->head = NULL;
l->tail = NULL;
}
curl_llist *
Curl_llist_alloc(curl_llist_dtor dtor)
{
curl_llist *list;
list = (curl_llist *)malloc(sizeof(curl_llist));
if(NULL == list)
return NULL;
Curl_llist_init(list, dtor);
return list;
}
/*
* Curl_llist_insert_next() returns 1 on success and 0 on failure.
*/
int
Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
{
curl_llist_element *ne =
(curl_llist_element *) malloc(sizeof(curl_llist_element));
if(!ne)
return 0;
ne->ptr = (void *) p;
if (list->size == 0) {
list->head = ne;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = ne;
}
else {
ne->next = e->next;
ne->prev = e;
if (e->next) {
e->next->prev = ne;
}
else {
list->tail = ne;
}
e->next = ne;
}
++list->size;
return 1;
}
int
Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
{
if (e == NULL || list->size == 0)
return 1;
if (e == list->head) {
list->head = e->next;
if (list->head == NULL)
list->tail = NULL;
else
e->next->prev = NULL;
} else {
e->prev->next = e->next;
if (!e->next)
list->tail = e->prev;
else
e->next->prev = e->prev;
}
list->dtor(user, e->ptr);
free(e);
--list->size;
return 1;
}
void
Curl_llist_destroy(curl_llist *list, void *user)
{
if(list) {
while (list->size > 0)
Curl_llist_remove(list, list->tail, user);
free(list);
}
}

56
Utilities/cmcurl/llist.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef __LLIST_H
#define __LLIST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <stddef.h>
typedef void (*curl_llist_dtor)(void *, void *);
typedef struct _curl_llist_element {
void *ptr;
struct _curl_llist_element *prev;
struct _curl_llist_element *next;
} curl_llist_element;
typedef struct _curl_llist {
curl_llist_element *head;
curl_llist_element *tail;
curl_llist_dtor dtor;
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 *);
#endif

348
Utilities/cmcurl/md5.c Normal file
View File

@ -0,0 +1,348 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#ifndef USE_SSLEAY
/* This code segment is only used if OpenSSL is not provided, as if it is
we use the MD5-function provided there instead. No good duplicating
code! */
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include <string.h>
/* UINT4 defines a four byte word */
typedef unsigned int UINT4;
/* MD5 context. */
struct md5_ctx {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
};
typedef struct md5_ctx MD5_CTX;
static void MD5_Init(struct md5_ctx *);
static void MD5_Update(struct md5_ctx *, unsigned char *, unsigned int);
static void MD5_Final(unsigned char [16], struct md5_ctx *);
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform(UINT4 [4], unsigned char [64]);
static void Encode(unsigned char *, UINT4 *, unsigned int);
static void Decode(UINT4 *, unsigned char *, unsigned int);
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
static void MD5_Init(struct md5_ctx *context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants. */
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
static void MD5_Update (struct md5_ctx *context, /* context */
unsigned char *input, /* input block */
unsigned int inputLen)/* length of input block */
{
unsigned int i, bufindex, partLen;
/* Compute number of bytes mod 64 */
bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - bufindex;
/* Transform as many times as possible. */
if (inputLen >= partLen) {
memcpy((void *)&context->buffer[bufindex], (void *)input, partLen);
MD5Transform(context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform(context->state, &input[i]);
bufindex = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy((void *)&context->buffer[bufindex], (void *)&input[i], inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
static void MD5_Final(unsigned char digest[16], /* message digest */
struct md5_ctx *context) /* context */
{
unsigned char bits[8];
unsigned int count, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64. */
count = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (count < 56) ? (56 - count) : (120 - count);
MD5_Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5_Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information. */
memset ((void *)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block. */
static void MD5Transform(UINT4 state[4],
unsigned char block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset((void *)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (unsigned char *output,
UINT4 *input,
unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (UINT4 *output,
unsigned char *input,
unsigned int len)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
#else
/* If OpenSSL is present */
#include <openssl/md5.h>
#include <string.h>
#endif
#include "md5.h"
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
unsigned char *input)
{
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, input, strlen((char *)input));
MD5_Final(outbuffer, &ctx);
}

29
Utilities/cmcurl/md5.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __MD5_H
#define __MD5_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
void Curl_md5it(unsigned char *output,
unsigned char *input);
#endif

293
Utilities/cmcurl/memdebug.c Normal file
View File

@ -0,0 +1,293 @@
#ifdef CURLDEBUG
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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"
#include <curl/curl.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#include "urldata.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
#include "curl_memory.h"
#include "memdebug.h"
struct memdebug {
size_t size;
double mem[1];
/* I'm hoping this is the thing with the strictest alignment
* requirements. That also means we waste some space :-( */
};
/*
* Note that these debug functions are very simple and they are meant to
* remain so. For advanced analysis, record a log file and write perl scripts
* to analyze them!
*
* Don't use these with multithreaded test programs!
*/
#define logfile curl_debuglogfile
FILE *curl_debuglogfile;
static bool memlimit; /* enable memory limit */
static long memsize; /* set number of mallocs allowed */
/* this sets the log file name */
void curl_memdebug(const char *logname)
{
if(logname)
logfile = fopen(logname, "w");
else
logfile = stderr;
}
/* This function sets the number of malloc() calls that should return
successfully! */
void curl_memlimit(long limit)
{
memlimit = TRUE;
memsize = limit;
}
/* returns TRUE if this isn't allowed! */
static bool countcheck(const char *func, int line, const char *source)
{
/* if source is NULL, then the call is made internally and this check
should not be made */
if(memlimit && source) {
if(!memsize) {
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
if(source)
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
return TRUE; /* RETURN ERROR! */
}
else
memsize--; /* countdown */
/* log the countdown */
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %ld ALLOCS left\n",
source, line, memsize);
}
return FALSE; /* allow this */
}
void *curl_domalloc(size_t wantedsize, int line, const char *source)
{
struct memdebug *mem;
size_t size;
if(countcheck("malloc", line, source))
return NULL;
/* alloc at least 64 bytes */
size = sizeof(struct memdebug)+wantedsize;
mem=(struct memdebug *)(Curl_cmalloc)(size);
if(mem) {
/* fill memory with junk */
memset(mem->mem, 0xA5, wantedsize);
mem->size = wantedsize;
}
if(logfile && source)
fprintf(logfile, "MEM %s:%d malloc(%zd) = %p\n",
source, line, wantedsize, mem ? mem->mem : 0);
return (mem ? mem->mem : NULL);
}
void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
int line, const char *source)
{
struct memdebug *mem;
size_t size, user_size;
if(countcheck("calloc", line, source))
return NULL;
/* alloc at least 64 bytes */
user_size = wanted_size * wanted_elements;
size = sizeof(struct memdebug) + user_size;
mem = (struct memdebug *)(Curl_cmalloc)(size);
if(mem) {
/* fill memory with zeroes */
memset(mem->mem, 0, user_size);
mem->size = user_size;
}
if(logfile && source)
fprintf(logfile, "MEM %s:%d calloc(%u,%u) = %p\n",
source, line, wanted_elements, wanted_size, mem ? mem->mem : 0);
return (mem ? mem->mem : NULL);
}
char *curl_dostrdup(const char *str, int line, const char *source)
{
char *mem;
size_t len;
curlassert(str != NULL);
if(countcheck("strdup", line, source))
return NULL;
len=strlen(str)+1;
mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
if (mem)
memcpy(mem, str, len);
if(logfile)
fprintf(logfile, "MEM %s:%d strdup(%p) (%zd) = %p\n",
source, line, str, len, mem);
return mem;
}
/* We provide a realloc() that accepts a NULL as pointer, which then
performs a malloc(). In order to work with ares. */
void *curl_dorealloc(void *ptr, size_t wantedsize,
int line, const char *source)
{
struct memdebug *mem=NULL;
size_t size = sizeof(struct memdebug)+wantedsize;
if(countcheck("realloc", line, source))
return NULL;
if(ptr)
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
mem=(struct memdebug *)(Curl_crealloc)(mem, size);
if(logfile)
fprintf(logfile, "MEM %s:%d realloc(0x%x, %zd) = %p\n",
source, line, ptr, wantedsize, mem?mem->mem:NULL);
if(mem) {
mem->size = wantedsize;
return mem->mem;
}
return NULL;
}
void curl_dofree(void *ptr, int line, const char *source)
{
struct memdebug *mem;
curlassert(ptr != NULL);
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
/* destroy */
memset(mem->mem, 0x13, mem->size);
/* free for real */
(Curl_cfree)(mem);
if(logfile)
fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
}
int curl_socket(int domain, int type, int protocol, int line,
const char *source)
{
int sockfd=(socket)(domain, type, protocol);
if(logfile && (sockfd!=-1))
fprintf(logfile, "FD %s:%d socket() = %d\n",
source, line, sockfd);
return sockfd;
}
int curl_accept(int s, void *saddr, void *saddrlen,
int line, const char *source)
{
struct sockaddr *addr = (struct sockaddr *)saddr;
socklen_t *addrlen = (socklen_t *)saddrlen;
int sockfd=(accept)(s, addr, addrlen);
if(logfile)
fprintf(logfile, "FD %s:%d accept() = %d\n",
source, line, sockfd);
return sockfd;
}
/* this is our own defined way to close sockets on *ALL* platforms */
int curl_sclose(int sockfd, int line, const char *source)
{
int res=sclose(sockfd);
if(logfile)
fprintf(logfile, "FD %s:%d sclose(%d)\n",
source, line, sockfd);
return res;
}
FILE *curl_fopen(const char *file, const char *mode,
int line, const char *source)
{
FILE *res=(fopen)(file, mode);
if(logfile)
fprintf(logfile, "FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
source, line, file, mode, res);
return res;
}
int curl_fclose(FILE *file, int line, const char *source)
{
int res;
curlassert(file != NULL);
res=(fclose)(file);
if(logfile)
fprintf(logfile, "FILE %s:%d fclose(%p)\n",
source, line, file);
return res;
}
#else
#ifdef VMS
int VOID_VAR_MEMDEBUG;
#else
/* we provide a fake do-nothing function here to avoid compiler warnings */
void curl_memdebug(void) {}
#endif /* VMS */
#endif /* CURLDEBUG */

108
Utilities/cmcurl/memdebug.h Normal file
View File

@ -0,0 +1,108 @@
#ifdef CURLDEBUG
#ifndef _CURL_MEDEBUG_H
#define _CURL_MEDEBUG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, 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$
***************************************************************************/
/*
* CAUTION: this header is designed to work when included by the app-side
* as well as the library. Do not mix with library internals!
*/
#include "setup.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <stdio.h>
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#define logfile curl_debuglogfile
extern FILE *logfile;
/* memory functions */
void *curl_domalloc(size_t size, int line, const char *source);
void *curl_docalloc(size_t elements, size_t size, int line, const char *source);
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source);
void curl_dofree(void *ptr, int line, const char *source);
char *curl_dostrdup(const char *str, int line, const char *source);
void curl_memdebug(const char *logname);
void curl_memlimit(long limit);
/* file descriptor manipulators */
int curl_socket(int domain, int type, int protocol, int line , const char *);
int curl_sclose(int sockfd, int, const char *source);
int curl_accept(int s, void *addr, void *addrlen,
int line, const char *source);
/* FILE functions */
FILE *curl_fopen(const char *file, const char *mode, int line,
const char *source);
int curl_fclose(FILE *file, int line, const char *source);
#ifndef MEMDEBUG_NODEFINES
/* 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 calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__)
#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
#define socket(domain,type,protocol)\
curl_socket(domain,type,protocol,__LINE__,__FILE__)
#undef accept /* for those with accept as a macro */
#define accept(sock,addr,len)\
curl_accept(sock,addr,len,__LINE__,__FILE__)
#define getaddrinfo(host,serv,hint,res) \
curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
curl_dogetnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \
__FILE__)
#define freeaddrinfo(data) \
curl_dofreeaddrinfo(data,__LINE__,__FILE__)
/* sclose is probably already defined, redefine it! */
#undef sclose
#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
/* ares-adjusted define: */
#undef closesocket
#define closesocket(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
#undef fopen
#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__)
#define fclose(file) curl_fclose(file,__LINE__,__FILE__)
#endif /* MEMDEBUG_NODEFINES */
#endif /* _CURL_MEDEBUG_H */
#endif /* CURLDEBUG */

Some files were not shown because too many files have changed in this diff Show More