ENH: Update Curl to 7.16.1

This commit is contained in:
Andy Cedilnik 2007-03-15 15:22:15 -04:00
parent f52d37c26f
commit 9314bb49e0
130 changed files with 21966 additions and 10276 deletions

View File

@ -0,0 +1,75 @@
# - Check if the source code provided in the SOURCE argument compiles.
# CHECK_C_SOURCE_COMPILES(SOURCE VAR)
# - macro which checks if the source code compiles
# SOURCE - source code to try to compile
# VAR - variable to store whether the source code compiled
#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
MACRO(CHECK_C_SOURCE_COMPILES SOURCE VAR)
IF("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN")
SET(message "${VAR}")
# If the number of arguments is greater than 2 (SOURCE VAR)
IF(${ARGC} GREATER 2)
# then add the third argument as a message
SET(message "${ARGV2} (${VAR})")
ENDIF(${ARGC} GREATER 2)
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ELSE(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
ENDIF(CMAKE_REQUIRED_LIBRARIES)
IF(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
ELSE(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
ENDIF(CMAKE_REQUIRED_INCLUDES)
SET(src "")
FOREACH(def ${EXTRA_DEFINES})
SET(src "${src}#define ${def} 1\n")
ENDFOREACH(def)
FOREACH(inc ${HEADER_INCLUDES})
SET(src "${src}#include <${inc}>\n")
ENDFOREACH(inc)
SET(src "${src}\nint main() { ${SOURCE} ; return 0; }")
SET(CMAKE_CONFIGURABLE_FILE_CONTENT "${src}")
CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
IMMEDIATE)
MESSAGE(STATUS "Performing Test ${message}")
TRY_COMPILE(${VAR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}"
"${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
IF(${VAR})
SET(${VAR} 1 CACHE INTERNAL "Test ${message}")
MESSAGE(STATUS "Performing Test ${message} - Success")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing C SOURCE FILE Test ${message} succeded with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${src}\n")
ELSE(${VAR})
MESSAGE(STATUS "Performing Test ${message} - Failed")
SET(${VAR} "" CACHE INTERNAL "Test ${message}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing C SOURCE FILE Test ${message} failed with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${src}\n")
ENDIF(${VAR})
ENDIF("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN")
ENDMACRO(CHECK_C_SOURCE_COMPILES)

View File

@ -0,0 +1,78 @@
# - Check if the source code provided in the SOURCE argument compiles and runs.
# CHECK_C_SOURCE_RUNS(SOURCE VAR)
# - macro which checks if the source code runs
# SOURCE - source code to try to compile
# VAR - variable to store size if the type exists.
#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
MACRO(CHECK_C_SOURCE_RUNS SOURCE VAR)
IF("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN")
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ELSE(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
ENDIF(CMAKE_REQUIRED_LIBRARIES)
IF(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
ELSE(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
ENDIF(CMAKE_REQUIRED_INCLUDES)
SET(src "")
FOREACH(def ${EXTRA_DEFINES})
SET(src "${src}#define ${def} 1\n")
ENDFOREACH(def)
FOREACH(inc ${HEADER_INCLUDES})
SET(src "${src}#include <${inc}>\n")
ENDFOREACH(inc)
SET(src "${src}\nint main() { ${SOURCE} ; return 0; }")
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src2.c"
"${src}\n")
EXEC_PROGRAM("${CMAKE_COMMAND}"
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp"
ARGS -E copy src2.c src.c)
MESSAGE(STATUS "Performing Test ${VAR}")
TRY_RUN(${VAR} ${VAR}_COMPILED
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}"
"${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
# if it did not compile make the return value fail code of 1
IF(NOT ${VAR}_COMPILED)
SET(${VAR} 1)
ENDIF(NOT ${VAR}_COMPILED)
# if the return value was 0 then it worked
SET(result_var ${${VAR}})
IF("${result_var}" EQUAL 0)
SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
MESSAGE(STATUS "Performing Test ${VAR} - Success")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
"${OUTPUT}\n"
"Return value: ${${VAR}}\n"
"Source file was:\n${src}\n")
ELSE("${result_var}" EQUAL 0)
MESSAGE(STATUS "Performing Test ${VAR} - Failed")
SET(${VAR} "" CACHE INTERNAL "Test ${VAR}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Return value: ${result_var}\n"
"Source file was:\n${src}\n")
ENDIF("${result_var}" EQUAL 0)
ENDIF("${VAR}" MATCHES "^${VAR}$" OR "${VAR}" MATCHES "UNKNOWN")
ENDMACRO(CHECK_C_SOURCE_RUNS)

View File

@ -0,0 +1,245 @@
INCLUDE(CheckCSourceCompiles)
SET(EXTRA_DEFINES "__unused1\n#undef inline\n#define __unused2")
SET(HEADER_INCLUDES)
SET(headers_hack)
MACRO(add_header_include check header)
IF(${check})
SET(headers_hack
"${headers_hack}\n#include <${header}>")
#SET(HEADER_INCLUDES
# ${HEADER_INCLUDES}
# "${header}")
ENDIF(${check})
ENDMACRO(add_header_include)
SET(signature_call_conv)
IF(HAVE_WINDOWS_H)
add_header_include(HAVE_WINDOWS_H "windows.h")
add_header_include(HAVE_WINSOCK2_H "winsock2.h")
add_header_include(HAVE_WINSOCK_H "winsock.h")
SET(EXTRA_DEFINES ${EXTRA_DEFINES}
"__unused7\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#define __unused3")
SET(signature_call_conv "PASCAL")
ELSE(HAVE_WINDOWS_H)
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
ENDIF(HAVE_WINDOWS_H)
SET(EXTRA_DEFINES_BACKUP "${EXTRA_DEFINES}")
SET(EXTRA_DEFINES "${EXTRA_DEFINES_BACKUP}\n${headers_hack}\n${extern_line}\n#define __unused5")
CHECK_C_SOURCE_COMPILES("recv(0, 0, 0, 0)" curl_cv_recv)
IF(curl_cv_recv)
# AC_CACHE_CHECK([types of arguments and return type for recv],
#[curl_cv_func_recv_args], [
#SET(curl_cv_func_recv_args "unknown")
#for recv_retv in 'int' 'ssize_t'; do
IF(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown")
FOREACH(recv_retv "ssize_t" "int")
FOREACH(recv_arg1 "int" "ssize_t" "SOCKET")
FOREACH(recv_arg2 "void *" "char *")
FOREACH(recv_arg3 "size_t" "int" "socklen_t" "unsigned int")
FOREACH(recv_arg4 "int" "unsigned int")
IF(NOT curl_cv_func_recv_done)
SET(curl_cv_func_recv_test "UNKNOWN")
SET(extern_line "extern ${recv_retv} ${signature_call_conv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})\;")
SET(EXTRA_DEFINES "${EXTRA_DEFINES_BACKUP}\n${headers_hack}\n${extern_line}\n#define __unused5")
CHECK_C_SOURCE_COMPILES("
${recv_arg1} s=0;
${recv_arg2} buf=0;
${recv_arg3} len=0;
${recv_arg4} flags=0;
${recv_retv} res = recv(s, buf, len, flags)"
curl_cv_func_recv_test
"${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})")
IF(curl_cv_func_recv_test)
SET(curl_cv_func_recv_args
"${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}")
SET(RECV_TYPE_ARG1 "${recv_arg1}")
SET(RECV_TYPE_ARG2 "${recv_arg2}")
SET(RECV_TYPE_ARG3 "${recv_arg3}")
SET(RECV_TYPE_ARG4 "${recv_arg4}")
SET(RECV_TYPE_RETV "${recv_retv}")
SET(HAVE_RECV 1)
SET(curl_cv_func_recv_done 1)
ENDIF(curl_cv_func_recv_test)
ENDIF(NOT curl_cv_func_recv_done)
ENDFOREACH(recv_arg4)
ENDFOREACH(recv_arg3)
ENDFOREACH(recv_arg2)
ENDFOREACH(recv_arg1)
ENDFOREACH(recv_retv)
ELSE(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown")
STRING(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
STRING(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
STRING(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}")
STRING(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}")
STRING(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}")
#MESSAGE("RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}")
#MESSAGE("RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}")
#MESSAGE("RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}")
#MESSAGE("RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}")
#MESSAGE("RECV_TYPE_RETV ${RECV_TYPE_RETV}")
ENDIF(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown")
IF("${curl_cv_func_recv_args}" STREQUAL "unknown")
MESSAGE(FATAL_ERROR "Cannot find proper types to use for recv args")
ENDIF("${curl_cv_func_recv_args}" STREQUAL "unknown")
ELSE(curl_cv_recv)
MESSAGE(FATAL_ERROR "Unable to link function recv")
ENDIF(curl_cv_recv)
SET(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
SET(HAVE_RECV 1)
CHECK_C_SOURCE_COMPILES("send(0, 0, 0, 0)" curl_cv_send)
IF(curl_cv_send)
# AC_CACHE_CHECK([types of arguments and return type for send],
#[curl_cv_func_send_args], [
#SET(curl_cv_func_send_args "unknown")
#for send_retv in 'int' 'ssize_t'; do
IF(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
FOREACH(send_retv "ssize_t" "int")
FOREACH(send_arg1 "int" "ssize_t" "SOCKET")
FOREACH(send_arg2 "const void *" "void *" "char *" "const char *")
FOREACH(send_arg3 "size_t" "int" "socklen_t" "unsigned int")
FOREACH(send_arg4 "int" "unsigned int")
IF(NOT curl_cv_func_send_done)
SET(curl_cv_func_send_test "UNKNOWN")
SET(extern_line "extern ${send_retv} ${signature_call_conv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})\;")
SET(EXTRA_DEFINES "${EXTRA_DEFINES_BACKUP}\n${headers_hack}\n${extern_line}\n#define __unused5")
CHECK_C_SOURCE_COMPILES("
${send_arg1} s=0;
${send_arg2} buf=0;
${send_arg3} len=0;
${send_arg4} flags=0;
${send_retv} res = send(s, buf, len, flags)"
curl_cv_func_send_test
"${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})")
IF(curl_cv_func_send_test)
#MESSAGE("Found arguments: ${curl_cv_func_send_test}")
STRING(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}")
STRING(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}")
SET(curl_cv_func_send_args
"${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}")
SET(SEND_TYPE_ARG1 "${send_arg1}")
SET(SEND_TYPE_ARG2 "${send_arg2}")
SET(SEND_TYPE_ARG3 "${send_arg3}")
SET(SEND_TYPE_ARG4 "${send_arg4}")
SET(SEND_TYPE_RETV "${send_retv}")
SET(HAVE_SEND 1)
SET(curl_cv_func_send_done 1)
ENDIF(curl_cv_func_send_test)
ENDIF(NOT curl_cv_func_send_done)
ENDFOREACH(send_arg4)
ENDFOREACH(send_arg3)
ENDFOREACH(send_arg2)
ENDFOREACH(send_arg1)
ENDFOREACH(send_retv)
ELSE(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
STRING(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
STRING(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
STRING(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}")
STRING(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}")
STRING(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}")
STRING(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}")
#MESSAGE("SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}")
#MESSAGE("SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}")
#MESSAGE("SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}")
#MESSAGE("SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}")
#MESSAGE("SEND_TYPE_RETV ${SEND_TYPE_RETV}")
#MESSAGE("SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}")
ENDIF(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
IF("${curl_cv_func_send_args}" STREQUAL "unknown")
MESSAGE(FATAL_ERROR "Cannot find proper types to use for send args")
ENDIF("${curl_cv_func_send_args}" STREQUAL "unknown")
SET(SEND_QUAL_ARG2 "const")
ELSE(curl_cv_send)
MESSAGE(FATAL_ERROR "Unable to link function send")
ENDIF(curl_cv_send)
SET(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
SET(HAVE_SEND 1)
SET(EXTRA_DEFINES "${EXTRA_DEFINES}\n${headers_hack}\n#define __unused5")
CHECK_C_SOURCE_COMPILES("int flag = MSG_NOSIGNAL" HAVE_MSG_NOSIGNAL)
SET(EXTRA_DEFINES "__unused1\n#undef inline\n#define __unused2")
SET(HEADER_INCLUDES)
SET(headers_hack)
MACRO(add_header_include check header)
IF(${check})
SET(headers_hack
"${headers_hack}\n#include <${header}>")
#SET(HEADER_INCLUDES
# ${HEADER_INCLUDES}
# "${header}")
ENDIF(${check})
ENDMACRO(add_header_include header)
IF(HAVE_WINDOWS_H)
SET(EXTRA_DEFINES ${EXTRA_DEFINES}
"__unused7\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#define __unused3")
add_header_include(HAVE_WINDOWS_H "windows.h")
add_header_include(HAVE_WINSOCK2_H "winsock2.h")
add_header_include(HAVE_WINSOCK_H "winsock.h")
ELSE(HAVE_WINDOWS_H)
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
add_header_include(TIME_WITH_SYS_TIME "time.h")
add_header_include(HAVE_TIME_H "time.h")
ENDIF(HAVE_WINDOWS_H)
SET(EXTRA_DEFINES "${EXTRA_DEFINES}\n${headers_hack}\n#define __unused5")
CHECK_C_SOURCE_COMPILES("struct timeval ts;\nts.tv_sec = 0;\nts.tv_usec = 0" HAVE_STRUCT_TIMEVAL)
INCLUDE(CheckCSourceRuns)
SET(EXTRA_DEFINES)
SET(HEADER_INCLUDES)
IF(HAVE_SYS_POLL_H)
SET(HEADER_INCLUDES "sys/poll.h")
ENDIF(HAVE_SYS_POLL_H)
CHECK_C_SOURCE_RUNS("return poll((void *)0, 0, 10 /*ms*/)" HAVE_POLL_FINE)
SET(HAVE_SIG_ATOMIC_T 1)
SET(EXTRA_DEFINES)
SET(HEADER_INCLUDES)
IF(HAVE_SIGNAL_H)
SET(HEADER_INCLUDES "signal.h")
SET(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
ENDIF(HAVE_SIGNAL_H)
CHECK_TYPE_SIZE("sig_atomic_t" SIZEOF_SIG_ATOMIC_T)
IF(HAVE_SIZEOF_SIG_ATOMIC_T)
CHECK_C_SOURCE_COMPILES("static volatile sig_atomic_t dummy = 0" HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
IF(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
SET(HAVE_SIG_ATOMIC_T_VOLATILE 1)
ENDIF(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
ENDIF(HAVE_SIZEOF_SIG_ATOMIC_T)
SET(CHECK_TYPE_SIZE_PREINCLUDE
"#undef inline")
IF(HAVE_WINDOWS_H)
SET(CHECK_TYPE_SIZE_PREINCLUDE "${CHECK_TYPE_SIZE_PREINCLUDE}
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>")
IF(HAVE_WINSOCK2_H)
SET(CHECK_TYPE_SIZE_PREINCLUDE "${CHECK_TYPE_SIZE_PREINCLUDE}\n#include <winsock2.h>")
ENDIF(HAVE_WINSOCK2_H)
ELSE(HAVE_WINDOWS_H)
IF(HAVE_SYS_SOCKET_H)
SET(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES}
"sys/socket.h")
ENDIF(HAVE_SYS_SOCKET_H)
IF(HAVE_NETINET_IN_H)
SET(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES}
"netinet/in.h")
ENDIF(HAVE_NETINET_IN_H)
IF(HAVE_ARPA_INET_H)
SET(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES}
"arpa/inet.h")
ENDIF(HAVE_ARPA_INET_H)
ENDIF(HAVE_WINDOWS_H)
CHECK_TYPE_SIZE("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
IF(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
SET(HAVE_STRUCT_SOCKADDR_STORAGE 1)
ENDIF(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)

View File

@ -5,7 +5,7 @@ INCLUDE_REGULAR_EXPRESSION("^.*$")
# Setup package meta-data
SET(PACKAGE "curl")
SET(VERSION "7.12.1")
SET(VERSION "7.16.1")
SET(PACKAGE_TARNAME "curl")
SET(PACKAGE_BUGREPORT " ")
SET(PACKAGE_NAME "curl")
@ -38,6 +38,7 @@ INCLUDE (CheckSymbolExists)
INCLUDE (CheckTypeSize)
SET(libCurl_SRCS
# amigaos.c - does not build on AmigaOS
base64.c
connect.c
content_encoding.c
@ -48,15 +49,15 @@ SET(libCurl_SRCS
file.c
formdata.c
ftp.c
getdate.c
getenv.c
getinfo.c
gtls.c
hash.c
hostares.c
hostasyn.c
hostip.c
hostip4.c
hostip6.c
hostip.c
hostsyn.c
hostthre.c
http.c
@ -68,20 +69,33 @@ SET(libCurl_SRCS
inet_ntop.c
inet_pton.c
krb4.c
ldap.c
llist.c
md5.c
memdebug.c
mprintf.c
multi.c
netrc.c
# nwlib.c - Not used
parsedate.c
progress.c
security.c
select.c
sendf.c
share.c
socks.c
speedcheck.c
splay.c
ssh.c
sslgen.c
ssluse.c
strdup.c
strequal.c
strerror.c
# strtok.c - specify later
strtoofft.c
telnet.c
tftp.c
timeval.c
transfer.c
url.c
@ -152,13 +166,16 @@ 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)
OPTION(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ON)
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 idn
CHECK_LIBRARY_EXISTS_CONCAT("idn" idna_to_ascii_lz HAVE_LIBIDN)
# Check for symbol dlopen (same as HAVE_LIBDL)
CHECK_LIBRARY_EXISTS("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
@ -202,7 +219,11 @@ MACRO(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
ENDMACRO(CHECK_INCLUDE_FILE_CONCAT)
# Check for header files
CHECK_INCLUDE_FILE_CONCAT("ws2tcpip.h" HAVE_WS2TCPIP_H)
CHECK_INCLUDE_FILE_CONCAT("winsock2.h" HAVE_WINSOCK2_H)
CHECK_INCLUDE_FILE_CONCAT("stdio.h" HAVE_STDIO_H)
CHECK_INCLUDE_FILE_CONCAT("windows.h" HAVE_WINDOWS_H)
CHECK_INCLUDE_FILE_CONCAT("winsock.h" HAVE_WINSOCK_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)
@ -226,6 +247,7 @@ IF(CMAKE_USE_OPENSSL)
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)
CHECK_INCLUDE_FILE_CONCAT("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H)
ENDIF(CMAKE_USE_OPENSSL)
IF(NOT CURL_SPECIAL_LIBZ)
@ -250,26 +272,35 @@ 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("sys/resource.h" HAVE_SYS_RESOURCE_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("locale.h" HAVE_LOCALE_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_INCLUDE_FILE_CONCAT("idn-free.h" HAVE_IDN_FREE_H)
CHECK_INCLUDE_FILE_CONCAT("idna.h" HAVE_IDNA_H)
CHECK_INCLUDE_FILE_CONCAT("tld.h" HAVE_TLD_H)
CHECK_INCLUDE_FILE_CONCAT("arpa/tftp.h" HAVE_ARPA_TFTP_H)
CHECK_INCLUDE_FILE_CONCAT("errno.h" HAVE_ERRNO_H)
CHECK_INCLUDE_FILE_CONCAT("libgen.h" HAVE_LIBGEN_H)
CHECK_INCLUDE_FILE_CONCAT("sys/filio.h" HAVE_SYS_FILIO_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" SIZEOF_LONG)
CHECK_TYPE_SIZE("__int64" SIZEOF___INT64)
CHECK_TYPE_SIZE("long double" SIZEOF_LONG_DOUBLE)
CHECK_TYPE_SIZE("time_t" SIZEOF_TIME_T)
IF(NOT HAVE_SIZEOF_SSIZE_T)
IF(SIZEOF_LONG EQUAL SIZEOF_SIZE_T)
SET(ssize_t long)
@ -281,11 +312,49 @@ ENDIF(NOT HAVE_SIZEOF_SSIZE_T)
IF(HAVE_SIZEOF_LONG_LONG)
SET(HAVE_LONGLONG 1)
SET(HAVE_LL 1)
ENDIF(HAVE_SIZEOF_LONG_LONG)
FIND_FILE(RANDOM_FILE urandom /dev)
MARK_AS_ADVANCED(RANDOM_FILE)
#strtoll \
#socket \
#select \
#strdup \
#strstr \
#strtok_r \
#uname \
#strcasecmp \
#stricmp \
#strcmpi \
#gethostbyaddr \
#gettimeofday \
#inet_addr \
#inet_ntoa \
#inet_pton \
#perror \
#closesocket \
#siginterrupt \
#sigaction \
#signal \
#getpass_r \
#strlcat \
#getpwuid \
#geteuid \
#dlopen \
#utime \
#sigsetjmp \
#basename \
#setlocale \
#ftruncate \
#pipe \
#poll \
#getprotobyname \
#getrlimit \
#setrlimit \
#fork
# Check for some functions that are used
CHECK_SYMBOL_EXISTS(socket "${CURL_INCLUDES}" HAVE_SOCKET)
CHECK_SYMBOL_EXISTS(poll "${CURL_INCLUDES}" HAVE_POLL)
@ -338,12 +407,22 @@ 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)
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)
CHECK_SYMBOL_EXISTS(fork "${CURL_INCLUDES}" HAVE_FORK)
CHECK_SYMBOL_EXISTS(pipe "${CURL_INCLUDES}" HAVE_PIPE)
CHECK_SYMBOL_EXISTS(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
CHECK_SYMBOL_EXISTS(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
CHECK_SYMBOL_EXISTS(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT)
CHECK_SYMBOL_EXISTS(idn_free "${CURL_INCLUDES}" HAVE_IDN_FREE)
CHECK_SYMBOL_EXISTS(idna_strerror "${CURL_INCLUDES}" HAVE_IDNA_STRERROR)
CHECK_SYMBOL_EXISTS(tld_strerror "${CURL_INCLUDES}" HAVE_TLD_STRERROR)
CHECK_SYMBOL_EXISTS(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
CHECK_SYMBOL_EXISTS(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
# only build compat strtok if we need to
IF (NOT HAVE_STRTOK_R)
@ -588,11 +667,14 @@ IF(CMAKE_COMPILER_IS_GNUCC AND APPLE)
COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
ENDIF(CMAKE_COMPILER_IS_GNUCC AND APPLE)
INCLUDE(CMake/OtherTests.cmake)
# The rest of the build
INCLUDE_DIRECTORIES(${LIBCURL_SOURCE_DIR})
INCLUDE_DIRECTORIES(${LIBCURL_BINARY_DIR})
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
ADD_DEFINITIONS(-DHAVE_CONFIG_H
-DCURL_STATICLIB)
CONFIGURE_FILE(${LIBCURL_SOURCE_DIR}/config.h.in
${LIBCURL_BINARY_DIR}/config.h)

View File

@ -46,7 +46,6 @@ IF(NOT UNIX)
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)

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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
@ -22,28 +22,53 @@
***************************************************************************/
#include "amigaos.h"
#include <stdio.h> /* for stderr */
#include <amitcp/socketbasetags.h>
struct Library *SocketBase = NULL;
extern int errno, h_errno;
#ifdef __libnix__
#include <stabs.h>
void __request(const char *msg);
#else
# define __request( msg ) Printf( msg "\n\a")
#endif
void amiga_cleanup()
{
if(SocketBase)
if(SocketBase) {
CloseLibrary(SocketBase);
SocketBase = NULL;
SocketBase = NULL;
}
}
BOOL amiga_init()
{
if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) {
fprintf(stderr, "No TCP/IP Stack running!\n\a");
__request("No TCP/IP Stack running!");
return FALSE;
}
if(SocketBaseTags(
SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
// SBTM_SETVAL(SBTC_HERRNOLONGPTR), (ULONG) &h_errno,
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
TAG_DONE)) {
__request("SocketBaseTags ERROR");
return FALSE;
}
#ifndef __libnix__
atexit(amiga_cleanup);
#endif
return TRUE;
}
#ifdef __libnix__
ADD2EXIT(amiga_cleanup,-50);
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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
@ -32,13 +32,19 @@
#include <proto/exec.h>
#include <proto/dos.h>
#include <bsdsocket.h>
#include <sys/socket.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)
#ifndef select
# define select(args...) WaitSelect( args, NULL)
#endif
#ifndef inet_ntoa
# define inet_ntoa(x) Inet_NtoA( x ## .s_addr)
#endif
#ifndef ioctl
# define ioctl(a,b,c,d) IoctlSocket( (LONG)a, (ULONG)b, (char*)c)
#endif
#define _AMIGASF 1
extern void amiga_cleanup();

View File

@ -39,7 +39,7 @@
/*
* The telnet options represented as strings
*/
static const char *telnetoptions[]=
static const char * const telnetoptions[]=
{
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD",
"NAME", "STATUS", "TIMING MARK", "RCTE",
@ -78,7 +78,7 @@ static const char *telnetoptions[]=
/*
* Then those numbers represented as strings:
*/
static const char *telnetcmds[]=
static const char * const telnetcmds[]=
{
"EOF", "SUSP", "ABORT", "EOR", "SE",
"NOP", "DMARK", "BRK", "IP", "AO",

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -40,28 +40,27 @@
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "urldata.h" /* for the SessionHandle definition */
#include "easyif.h" /* for Curl_convert_... prototypes */
#include "base64.h"
#include "curl_memory.h"
#include "memory.h"
/* include memdebug.h last */
#include "memdebug.h"
/* ---- Base64 Encoding/Decoding Table --- */
static const char table64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void decodeQuantum(unsigned char *dest, const char *src)
{
unsigned int x = 0;
int i;
char *found;
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;
if((found = strchr(table64, src[i])))
x = (x << 6) + (unsigned int)(found - table64);
else if(src[i] == '=')
x = (x << 6);
}
@ -76,43 +75,63 @@ static void decodeQuantum(unsigned char *dest, const char *src)
/*
* 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.
* Given a base64 string at src, decode it and return an allocated memory in
* the *outptr. Returns the length of the decoded data.
*/
size_t Curl_base64_decode(const char *src, char *dest)
size_t Curl_base64_decode(const char *src, unsigned char **outptr)
{
int length = 0;
int equalsTerm = 0;
int i;
int numQuantums;
unsigned char lastQuantum[3];
size_t rawlen;
size_t rawlen=0;
unsigned char *newstr;
*outptr = NULL;
while((src[length] != '=') && src[length])
length++;
while(src[length+equalsTerm] == '=')
/* A maximum of two = padding characters is allowed */
if(src[length] == '=') {
equalsTerm++;
if(src[length+equalsTerm] == '=')
equalsTerm++;
}
numQuantums = (length + equalsTerm) / 4;
/* Don't allocate a buffer if the decoded length is 0 */
if (numQuantums <= 0)
return 0;
rawlen = (numQuantums * 3) - equalsTerm;
/* The buffer must be large enough to make room for the last quantum
(which may be partially thrown out) and the zero terminator. */
newstr = malloc(rawlen+4);
if(!newstr)
return 0;
*outptr = newstr;
/* Decode all but the last quantum (which may not decode to a
multiple of 3 bytes) */
for(i = 0; i < numQuantums - 1; i++) {
decodeQuantum((unsigned char *)dest, src);
dest += 3; src += 4;
decodeQuantum((unsigned char *)newstr, src);
newstr += 3; src += 4;
}
/* This final decode may actually read slightly past the end of the buffer
if the input string is missing pad bytes. This will almost always be
harmless. */
decodeQuantum(lastQuantum, src);
for(i = 0; i < 3 - equalsTerm; i++)
dest[i] = lastQuantum[i];
newstr[i] = lastQuantum[i];
newstr[i] = 0; /* zero terminate */
return rawlen;
}
/* ---- Base64 Encoding --- */
static char table64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
* Curl_base64_encode()
*
@ -121,7 +140,8 @@ static char table64[]=
* went wrong, -1 is returned.
*
*/
size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
size_t Curl_base64_encode(struct SessionHandle *data,
const char *inp, size_t insize, char **outptr)
{
unsigned char ibuf[3];
unsigned char obuf[4];
@ -129,6 +149,9 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
int inputparts;
char *output;
char *base64data;
#ifdef CURL_DOES_CONVERSIONS
char *convbuf;
#endif
char *indata = (char *)inp;
@ -141,6 +164,28 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
if(NULL == output)
return 0;
#ifdef CURL_DOES_CONVERSIONS
/*
* The base64 data needs to be created using the network encoding
* not the host encoding. And we can't change the actual input
* so we copy it to a buffer, translate it, and use that instead.
*/
if(data) {
convbuf = (char*)malloc(insize);
if(!convbuf) {
return 0;
}
memcpy(convbuf, indata, insize);
if(CURLE_OK != Curl_convert_to_network(data, convbuf, insize)) {
free(convbuf);
return 0;
}
indata = convbuf; /* switch to the converted buffer */
}
#else
(void)data;
#endif
while(insize > 0) {
for (i = inputparts = 0; i < 3; i++) {
if(insize > 0) {
@ -153,10 +198,12 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
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;
obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
((ibuf[1] & 0xF0) >> 4));
obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
((ibuf[2] & 0xC0) >> 6));
obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
switch(inputparts) {
case 1: /* only one byte read */
@ -183,6 +230,10 @@ size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
*output=0;
*outptr = base64data; /* make it return the actual data memory */
#ifdef CURL_DOES_CONVERSIONS
if(data)
free(convbuf);
#endif
return strlen(base64data); /* return the length of the new data */
}
/* ---- End of Base64 Encoding ---- */
@ -205,14 +256,26 @@ int main(int argc, char **argv, char **envp)
size_t base64Len;
unsigned char *data;
int dataLen;
struct SessionHandle *handle = NULL;
#ifdef CURL_DOES_CONVERSIONS
/* get a Curl handle so Curl_base64_encode can translate properly */
handle = curl_easy_init();
if(handle == NULL) {
fprintf(stderr, "Error: curl_easy_init failed\n");
return 0;
}
#endif
data = (unsigned char *)suck(&dataLen);
base64Len = Curl_base64_encode(data, dataLen, &base64);
base64Len = Curl_base64_encode(handle, data, dataLen, &base64);
fprintf(stderr, "%d\n", base64Len);
fprintf(stdout, "%s", base64);
fprintf(stdout, "%s\n", base64);
free(base64); free(data);
#ifdef CURL_DOES_CONVERSIONS
curl_easy_cleanup(handle);
#endif
return 0;
}
#endif
@ -235,10 +298,17 @@ int main(int argc, char **argv, char **envp)
unsigned char *data;
int dataLen;
int i, j;
#ifdef CURL_DOES_CONVERSIONS
/* get a Curl handle so main can translate properly */
struct SessionHandle *handle = curl_easy_init();
if(handle == NULL) {
fprintf(stderr, "Error: curl_easy_init failed\n");
return 0;
}
#endif
base64 = (char *)suck(&base64Len);
data = (unsigned char *)malloc(base64Len * 3/4 + 8);
dataLen = Curl_base64_decode(base64, data);
dataLen = Curl_base64_decode(base64, &data);
fprintf(stderr, "%d\n", dataLen);
@ -253,13 +323,21 @@ int main(int argc, char **argv, char **envp)
printf(" | ");
for(j=0; j < 0x10; j++)
if((j+i) < dataLen)
printf("%c", isgraph(data[i+j])?data[i+j]:'.');
else
if((j+i) < dataLen) {
#ifdef CURL_DOES_CONVERSIONS
if(CURLE_OK !=
Curl_convert_from_network(handle, &data[i+j], (size_t)1))
data[i+j] = '.';
#endif /* CURL_DOES_CONVERSIONS */
printf("%c", ISGRAPH(data[i+j])?data[i+j]:'.');
} else
break;
puts("");
}
#ifdef CURL_DOES_CONVERSIONS
curl_easy_cleanup(handle);
#endif
free(base64); free(data);
return 0;
}

View File

@ -1,18 +1,18 @@
#ifndef __BASE64_H
#define __BASE64_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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.
@ -22,6 +22,7 @@
*
* $Id$
***************************************************************************/
size_t Curl_base64_encode(const char *input, size_t size, char **str);
size_t Curl_base64_decode(const char *source, char *dest);
size_t Curl_base64_encode(struct SessionHandle *data,
const char *input, size_t size, char **str);
size_t Curl_base64_decode(const char *source, unsigned char **outptr);
#endif

View File

@ -1,4 +1,13 @@
/* lib/config.h.in. Generated from configure.in by autoheader. */
/* lib/config.h.in. Generated from configure.ac by autoheader. */
/* when building libcurl itself */
#cmakedefine BUILDING_LIBCURL ${BUILDING_LIBCURL}
/* to disable cookies support */
#cmakedefine CURL_DISABLE_COOKIES ${CURL_DISABLE_COOKIES}
/* to disable cryptographic authentication */
#cmakedefine CURL_DISABLE_CRYPTO_AUTH ${CURL_DISABLE_CRYPTO_AUTH}
/* to disable DICT */
#cmakedefine CURL_DISABLE_DICT ${CURL_DISABLE_DICT}
@ -9,9 +18,6 @@
/* 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}
@ -21,24 +27,66 @@
/* to disable TELNET */
#cmakedefine CURL_DISABLE_TELNET ${CURL_DISABLE_TELNET}
/* to disable TFTP */
#cmakedefine CURL_DISABLE_TFTP ${CURL_DISABLE_TFTP}
/* to disable verbose strings */
#cmakedefine CURL_DISABLE_VERBOSE_STRINGS ${CURL_DISABLE_VERBOSE_STRINGS}
/* to make a symbol visible */
#cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL}
/* to enable hidden symbols */
#cmakedefine CURL_HIDDEN_SYMBOLS ${CURL_HIDDEN_SYMBOLS}
/* when not building a shared library */
#cmakedefine CURL_STATICLIB ${CURL_STATICLIB}
/* Set to explicitly specify we don't want to use thread-safe functions */
#cmakedefine DISABLED_THREADSAFE ${DISABLED_THREADSAFE}
/* lber dynamic library file */
#cmakedefine DL_LBER_FILE ${DL_LBER_FILE}
/* ldap dynamic library file */
#cmakedefine DL_LDAP_FILE ${DL_LDAP_FILE}
/* 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 the type qualifier of arg 1 for getnameinfo. */
#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1}
/* Define to the type of arg 1 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1}
/* Define to the type of arg 2 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2}
/* Define to the type of args 4 and 6 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46}
/* Define to the type of arg 7 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7}
/* 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 <arpa/tftp.h> header file. */
#cmakedefine HAVE_ARPA_TFTP_H ${HAVE_ARPA_TFTP_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 `basename' function. */
#cmakedefine HAVE_BASENAME ${HAVE_BASENAME}
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET ${HAVE_CLOSESOCKET}
@ -60,6 +108,12 @@
/* Define to 1 if you have the `dlopen' function. */
#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN}
/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES ${HAVE_ENGINE_LOAD_BUILTIN_ENGINES}
/* Define to 1 if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H}
/* Define to 1 if you have the <err.h> header file. */
#cmakedefine HAVE_ERR_H ${HAVE_ERR_H}
@ -69,6 +123,12 @@
/* use FIONBIO for non-blocking sockets */
#cmakedefine HAVE_FIONBIO ${HAVE_FIONBIO}
/* Define to 1 if you have the `fork' function. */
#cmakedefine HAVE_FORK ${HAVE_FORK}
/* Define to 1 if you have the `ftruncate' function. */
#cmakedefine HAVE_FTRUNCATE ${HAVE_FTRUNCATE}
/* Define if getaddrinfo exists and works */
#cmakedefine HAVE_GETADDRINFO ${HAVE_GETADDRINFO}
@ -93,12 +153,21 @@
/* gethostbyname_r() takes 6 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_6 ${HAVE_GETHOSTBYNAME_R_6}
/* Define to 1 if you have the getnameinfo function. */
#cmakedefine HAVE_GETNAMEINFO ${HAVE_GETNAMEINFO}
/* Define to 1 if you have the `getpass_r' function. */
#cmakedefine HAVE_GETPASS_R ${HAVE_GETPASS_R}
/* Define to 1 if you have the `getprotobyname' function. */
#cmakedefine HAVE_GETPROTOBYNAME ${HAVE_GETPROTOBYNAME}
/* Define to 1 if you have the `getpwuid' function. */
#cmakedefine HAVE_GETPWUID ${HAVE_GETPWUID}
/* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT ${HAVE_GETRLIMIT}
/* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY}
@ -111,12 +180,18 @@
/* if you have the gssapi libraries */
#cmakedefine HAVE_GSSAPI ${HAVE_GSSAPI}
/* if you have the GNU gssapi libraries */
#cmakedefine HAVE_GSSGNU ${HAVE_GSSGNU}
/* 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 `idna_strerror' function. */
#cmakedefine HAVE_IDNA_STRERROR ${HAVE_IDNA_STRERROR}
/* Define to 1 if you have the `idn_free' function. */
#cmakedefine HAVE_IDN_FREE ${HAVE_IDN_FREE}
@ -159,12 +234,12 @@
/* 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 <libgen.h> header file. */
#cmakedefine HAVE_LIBGEN_H ${HAVE_LIBGEN_H}
/* Define to 1 if you have the `idn' library (-lidn). */
#cmakedefine HAVE_LIBIDN ${HAVE_LIBIDN}
@ -177,6 +252,12 @@
/* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET ${HAVE_LIBSOCKET}
/* Define to 1 if you have the `ssh2' library (-lssh2). */
#cmakedefine HAVE_LIBSSH2 ${HAVE_LIBSSH2}
/* Define to 1 if you have the <libssh2.h> header file. */
#cmakedefine HAVE_LIBSSH2_H ${HAVE_LIBSSH2_H}
/* Define to 1 if you have the `ssl' library (-lssl). */
#cmakedefine HAVE_LIBSSL ${HAVE_LIBSSL}
@ -186,18 +267,27 @@
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H}
/* if your compiler supports LL */
#cmakedefine HAVE_LL ${HAVE_LL}
/* Define to 1 if you have the <locale.h> header file. */
#cmakedefine HAVE_LOCALE_H ${HAVE_LOCALE_H}
/* Define to 1 if you have the `localtime_r' function. */
#cmakedefine HAVE_LOCALTIME_R ${HAVE_LOCALTIME_R}
/* if your compiler supports 'long long' */
/* if your compiler supports long long */
#cmakedefine HAVE_LONGLONG ${HAVE_LONGLONG}
/* Define to 1 if you have the <malloc.h> header file. */
/* 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 MSG_NOSIGNAL flag. */
#cmakedefine HAVE_MSG_NOSIGNAL ${HAVE_MSG_NOSIGNAL}
/* Define to 1 if you have the <netdb.h> header file. */
#cmakedefine HAVE_NETDB_H ${HAVE_NETDB_H}
@ -210,9 +300,12 @@
/* 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 */
/* Define to 1 if NI_WITHSCOPEID exists and works. */
#cmakedefine HAVE_NI_WITHSCOPEID ${HAVE_NI_WITHSCOPEID}
/* Defined if no inet_pton() prototype available */
#cmakedefine HAVE_NO_INET_PTON_PROTO ${HAVE_NO_INET_PTON_PROTO}
/* we have no strerror_r() proto */
#cmakedefine HAVE_NO_STRERROR_R_DECL ${HAVE_NO_STRERROR_R_DECL}
@ -228,6 +321,9 @@
/* 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/pkcs12.h> header file. */
#cmakedefine HAVE_OPENSSL_PKCS12_H ${HAVE_OPENSSL_PKCS12_H}
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#cmakedefine HAVE_OPENSSL_RSA_H ${HAVE_OPENSSL_RSA_H}
@ -246,6 +342,9 @@
/* Define to 1 if you have the `perror' function. */
#cmakedefine HAVE_PERROR ${HAVE_PERROR}
/* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE ${HAVE_PIPE}
/* Define to 1 if you have the `poll' function. */
#cmakedefine HAVE_POLL ${HAVE_POLL}
@ -267,15 +366,27 @@
/* Define to 1 if you have the `RAND_status' function. */
#cmakedefine HAVE_RAND_STATUS ${HAVE_RAND_STATUS}
/* Define to 1 if you have the recv function. */
#cmakedefine HAVE_RECV ${HAVE_RECV}
/* 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. */
/* Define to 1 if you have the select function. */
#cmakedefine HAVE_SELECT ${HAVE_SELECT}
/* Define to 1 if you have the send function. */
#cmakedefine HAVE_SEND ${HAVE_SEND}
/* 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 `setlocale' function. */
#cmakedefine HAVE_SETLOCALE ${HAVE_SETLOCALE}
/* Define to 1 if you have the `setrlimit' function. */
#cmakedefine HAVE_SETRLIMIT ${HAVE_SETRLIMIT}
/* Define to 1 if you have the <sgtty.h> header file. */
#cmakedefine HAVE_SGTTY_H ${HAVE_SGTTY_H}
@ -288,9 +399,18 @@
/* Define to 1 if you have the `signal' function. */
#cmakedefine HAVE_SIGNAL ${HAVE_SIGNAL}
/* Define to 1 if you have the <signal.h> header file. */
#cmakedefine HAVE_SIGNAL_H ${HAVE_SIGNAL_H}
/* If you have sigsetjmp */
#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP}
/* Define to 1 if sig_atomic_t is an available typedef. */
#cmakedefine HAVE_SIG_ATOMIC_T ${HAVE_SIG_ATOMIC_T}
/* Define to 1 if sig_atomic_t is already defined as volatile. */
#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE ${HAVE_SIG_ATOMIC_T_VOLATILE}
/* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET ${HAVE_SOCKET}
@ -306,6 +426,9 @@
/* 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 <stdio.h> header file. */
#cmakedefine HAVE_STDIO_H ${HAVE_STDIO_H}
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H}
@ -321,9 +444,6 @@
/* 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}
@ -348,6 +468,15 @@
/* Define to 1 if you have the `strtoll' function. */
#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL}
/* if struct sockaddr_storage is defined */
#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE ${HAVE_STRUCT_SOCKADDR_STORAGE}
/* Define to 1 if you have the timeval struct. */
#cmakedefine HAVE_STRUCT_TIMEVAL ${HAVE_STRUCT_TIMEVAL}
/* Define to 1 if you have the <sys/filio.h> header file. */
#cmakedefine HAVE_SYS_FILIO_H ${HAVE_SYS_FILIO_H}
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H ${HAVE_SYS_IOCTL_H}
@ -357,6 +486,9 @@
/* 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/resource.h> header file. */
#cmakedefine HAVE_SYS_RESOURCE_H ${HAVE_SYS_RESOURCE_H}
/* Define to 1 if you have the <sys/select.h> header file. */
#cmakedefine HAVE_SYS_SELECT_H ${HAVE_SYS_SELECT_H}
@ -378,12 +510,6 @@
/* 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}
@ -393,6 +519,12 @@
/* 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 <tld.h> header file. */
#cmakedefine HAVE_TLD_H ${HAVE_TLD_H}
/* Define to 1 if you have the `tld_strerror' function. */
#cmakedefine HAVE_TLD_STRERROR ${HAVE_TLD_STRERROR}
/* Define to 1 if you have the `uname' function. */
#cmakedefine HAVE_UNAME ${HAVE_UNAME}
@ -405,44 +537,74 @@
/* 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. */
/* Define to 1 if you have the windows.h header file. */
#cmakedefine HAVE_WINDOWS_H ${HAVE_WINDOWS_H}
/* Define to 1 if you have the winsock2.h header file. */
#cmakedefine HAVE_WINSOCK2_H ${HAVE_WINSOCK2_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 ws2tcpip.h header file. */
#cmakedefine HAVE_WS2TCPIP_H ${HAVE_WS2TCPIP_H}
/* 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}
/* If you lack a fine basename() prototype */
#cmakedefine NEED_BASENAME_PROTO ${NEED_BASENAME_PROTO}
/* Define to 1 if you need the malloc.h header file even with stdlib.h */
#cmakedefine NEED_MALLOC_H ${NEED_MALLOC_H}
/* need REENTRANT defined */
#cmakedefine NEED_REENTRANT ${NEED_REENTRANT}
/* cpu-machine-OS */
#define OS "${OPERATING_SYSTEM}"
#define OS "${OPERATING_SYSTEM}"
/* Name of package */
#cmakedefine PACKAGE "${PACKAGE}"
#cmakedefine PACKAGE "${PACKAGE}"
/* Define to the address where bug reports for this package should be sent. */
#cmakedefine PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}"
#cmakedefine PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}"
/* Define to the full name of this package. */
#cmakedefine PACKAGE_NAME "${PACKAGE_NAME}"
#cmakedefine PACKAGE_NAME "${PACKAGE_NAME}"
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_STRING "${PACKAGE_STRING}"
#cmakedefine PACKAGE_STRING "${PACKAGE_STRING}"
/* Define to the one symbol short name of this package. */
#cmakedefine PACKAGE_TARNAME "${PACKAGE_TARNAME}"
#cmakedefine PACKAGE_TARNAME "${PACKAGE_TARNAME}"
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION "${PACKAGE_VERSION}"
#cmakedefine PACKAGE_VERSION "${PACKAGE_VERSION}"
/* a suitable file to read random data from */
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
/* Define to the type of arg 1 for recv. */
#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}
/* Define to the type of arg 2 for recv. */
#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}
/* Define to the type of arg 3 for recv. */
#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}
/* Define to the type of arg 4 for recv. */
#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}
/* Define to the function return type for recv. */
#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
/* Define as the return type of signal handlers (`int' or `void'). */
#cmakedefine RETSIGTYPE ${RETSIGTYPE}
@ -456,12 +618,36 @@
/* 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. */
/* Define to the type qualifier of arg 2 for send. */
#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}
/* Define to the type of arg 1 for send. */
#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}
/* Define to the type of arg 2 for send. */
#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}
/* Define to the type of arg 3 for send. */
#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}
/* Define to the type of arg 4 for send. */
#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}
/* Define to the function return type for send. */
#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV}
/* The size of `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. */
/* The size of `long', as computed by sizeof. */
#cmakedefine SIZEOF_LONG ${SIZEOF_LONG}
/* The size of `size_t', as computed by sizeof. */
#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}
/* The size of `time_t', as computed by sizeof. */
#cmakedefine SIZEOF_TIME_T ${SIZEOF_TIME_T}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS ${STDC_HEADERS}
@ -471,11 +657,29 @@
/* Define if you want to enable ares support */
#cmakedefine USE_ARES ${USE_ARES}
/* if GnuTLS is enabled */
#cmakedefine USE_GNUTLS ${USE_GNUTLS}
/* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 ${USE_LIBSSH2}
/* If you want to build curl with the built-in manual */
#cmakedefine USE_MANUAL ${USE_MANUAL}
/* if OpenSSL is in use */
#cmakedefine USE_OPENSSL ${USE_OPENSSL}
/* if SSL is enabled */
#cmakedefine USE_SSLEAY ${USE_SSLEAY}
/* to enable SSPI support */
#cmakedefine USE_WINDOWS_SSPI ${USE_WINDOWS_SSPI}
/* Version number of package */
#cmakedefine VERSION "${VERSION}"
#cmakedefine VERSION "${VERSION}"
/* Define to avoid automatic inclusion of winsock.h */
#cmakedefine WIN32_LEAN_AND_MEAN ${WIN32_LEAN_AND_MEAN}
/* Define to 1 if on AIX 3.
System headers sometimes define this.
@ -490,13 +694,16 @@
/* Define for large files, on AIX-style hosts. */
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
/* define this if you need it to compile thread-safe code */
#cmakedefine _THREAD_SAFE ${_THREAD_SAFE}
/* 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. */
/* Define to `unsigned int' if <sys/types.h> does not define. */
#cmakedefine size_t ${size_t}
/* type to use in place of socklen_t if not defined */
@ -505,8 +712,5 @@
/* 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}"

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -25,7 +25,9 @@
#ifndef WIN32
/* headers for non-win32 */
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -67,7 +69,7 @@
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#ifdef VMS
#ifdef VMS
#include <in.h>
#include <inet.h>
#endif
@ -82,8 +84,7 @@
#define FALSE 0
#endif
#ifdef WIN32
#include <windows.h>
#ifdef USE_WINSOCK
#define EINPROGRESS WSAEINPROGRESS
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EISCONN WSAEISCONN
@ -96,7 +97,12 @@
#include "if2ip.h"
#include "strerror.h"
#include "connect.h"
#include "curl_memory.h"
#include "memory.h"
#include "select.h"
#include "url.h" /* for Curl_safefree() */
#include "multiif.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "inet_ntop.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -105,18 +111,18 @@ static bool verifyconnect(curl_socket_t sockfd, int *error);
static curl_socket_t
singleipconnect(struct connectdata *conn,
Curl_addrinfo *ai, /* start connecting to this */
const 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.
* Curl_sockerrno() returns the *socket-related* errno (or equivalent) on this
* platform to hide platform specific for the function that calls this.
*/
int Curl_ourerrno(void)
int Curl_sockerrno(void)
{
#ifdef WIN32
return (int)GetLastError();
#ifdef USE_WINSOCK
return (int)WSAGetLastError();
#else
return errno;
#endif
@ -131,72 +137,62 @@ int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */)
{
#undef SETBLOCK
#define SETBLOCK 0
#ifdef HAVE_O_NONBLOCK
{
/* most recent unix versions */
int flags;
/* 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));
}
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));
#undef SETBLOCK
#define SETBLOCK 1
#endif
#ifdef HAVE_FIONBIO
{
/* older unix versions */
int flags;
#if defined(HAVE_FIONBIO) && (SETBLOCK == 0)
/* older unix versions */
int flags;
flags = nonblock;
return ioctl(sockfd, FIONBIO, &flags);
}
#ifdef SETBLOCK
# undef SETBLOCK
#endif
flags = nonblock;
return ioctl(sockfd, FIONBIO, &flags);
#undef SETBLOCK
#define SETBLOCK 2
#endif
#ifdef HAVE_IOCTLSOCKET
#if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0)
/* Windows? */
unsigned long flags;
flags = nonblock;
return ioctlsocket(sockfd, FIONBIO, &flags);
#undef SETBLOCK
#define SETBLOCK 3
#endif
#ifdef HAVE_IOCTLSOCKET_CASE
#if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0)
/* presumably for Amiga */
return IoctlSocket(sockfd, FIONBIO, (long)nonblock);
#ifdef SETBLOCK
# undef SETBLOCK
#endif
#undef SETBLOCK
#define SETBLOCK 4
#endif
#ifdef HAVE_SO_NONBLOCK
#if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0)
/* BeOS */
long b = nonblock ? 1 : 0;
return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
#ifdef SETBLOCK
# undef SETBLOCK
#endif
#undef SETBLOCK
#define SETBLOCK 5
#endif
#ifdef HAVE_DISABLED_NONBLOCKING
(void)nonblock;
(void)sockfd;
return 0; /* returns success */
#ifdef SETBLOCK
# undef SETBLOCK
#endif
#undef SETBLOCK
#define SETBLOCK 6
#endif
#ifndef SETBLOCK
#if (SETBLOCK == 0)
#error "no non-blocking method was found/used/set"
#endif
}
@ -219,30 +215,16 @@ 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);
(void)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);
rc = Curl_select(CURL_SOCKET_BAD, sockfd, (int)timeout_msec);
if(-1 == rc)
/* error, no connect here, try next */
return WAITCONN_SELECT_ERROR;
@ -251,7 +233,7 @@ int waitconnect(curl_socket_t sockfd, /* socket */
/* timeout, no connect today */
return WAITCONN_TIMEOUT;
if(FD_ISSET(sockfd, &errfd))
if(rc & CSELECT_ERR)
/* error condition caught */
return WAITCONN_FDSET_ERROR;
@ -262,14 +244,19 @@ int waitconnect(curl_socket_t sockfd, /* socket */
static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd)
{
#ifdef HAVE_INET_NTOA
bool bindworked = FALSE;
struct SessionHandle *data = conn->data;
struct sockaddr_in me;
struct sockaddr *sock = NULL; /* bind to this address */
socklen_t socksize; /* size of the data sock points to */
unsigned short port = data->set.localport; /* use this port number, 0 for
"random" */
/* how many port numbers to try to bind to, increasing one at a time */
int portnum = data->set.localportrange;
/*************************************************************
* Select device to bind socket to
*************************************************************/
if (strlen(data->set.device)<255) {
if (data->set.device && (strlen(data->set.device)<255) ) {
struct Curl_dns_entry *h=NULL;
char myhost[256] = "";
in_addr_t in;
@ -288,8 +275,10 @@ static CURLcode bindlocal(struct connectdata *conn,
if(rc == CURLRESOLV_PENDING)
(void)Curl_wait_for_resolv(conn, &h);
if(h)
if(h) {
was_iface = TRUE;
Curl_resolv_unlock(data, h);
}
}
if(!was_iface) {
@ -301,9 +290,17 @@ static CURLcode bindlocal(struct connectdata *conn,
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(h) {
if(in == CURL_INADDR_NONE)
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
Curl_inet_ntop(h->addr->ai_addr->sa_family,
&((struct sockaddr_in*)h->addr->ai_addr)->sin_addr,
myhost, sizeof myhost);
else
/* we know data->set.device is shorter than the myhost array */
strcpy(myhost, data->set.device);
Curl_resolv_unlock(data, h);
}
}
if(! *myhost) {
@ -317,7 +314,7 @@ static CURLcode bindlocal(struct connectdata *conn,
return CURLE_HTTP_PORT_FAILED;
}
infof(data, "We bind local end to %s\n", myhost);
infof(data, "Bind local address to %s\n", myhost);
#ifdef SO_BINDTODEVICE
/* I am not sure any other OSs than Linux that provide this feature, and
@ -335,7 +332,7 @@ static CURLcode bindlocal(struct connectdata *conn,
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())); */
sockfd, data->set.device, Curl_strerror(Curl_sockerrno())); */
infof(data, "SO_BINDTODEVICE %s failed\n",
data->set.device);
/* This is typically "errno 1, error: Operation not permitted" if
@ -345,59 +342,78 @@ static CURLcode bindlocal(struct connectdata *conn,
#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;
}
if (CURL_INADDR_NONE == in) {
failf(data,"couldn'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;
if ( h ) {
Curl_addrinfo *addr = h->addr;
sock = addr->ai_addr;
socksize = addr->ai_addrlen;
}
else
return CURLE_HTTP_PORT_FAILED;
}
else if(port) {
/* if a local port number is requested but no local IP, extract the
address from the socket */
memset(&me, 0, sizeof(struct sockaddr));
me.sin_family = AF_INET;
me.sin_addr.s_addr = INADDR_ANY;
sock = (struct sockaddr *)&me;
socksize = sizeof(struct sockaddr);
}
else
/* no local kind of binding was requested */
return CURLE_OK;
} /* end of device selection support */
#endif /* end of HAVE_INET_NTOA */
do {
/* Set port number to bind to, 0 makes the system pick one */
if(sock->sa_family == AF_INET)
((struct sockaddr_in *)sock)->sin_port = htons(port);
#ifdef ENABLE_IPV6
else
((struct sockaddr_in6 *)sock)->sin6_port = htons(port);
#endif
if( bind(sockfd, sock, socksize) >= 0) {
/* we succeeded to bind */
struct Curl_sockaddr_storage add;
socklen_t size;
size = sizeof(add);
if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
failf(data, "getsockname() failed");
return CURLE_HTTP_PORT_FAILED;
}
/* We re-use/clobber the port variable here below */
if(((struct sockaddr *)&add)->sa_family == AF_INET)
port = ntohs(((struct sockaddr_in *)&add)->sin_port);
#ifdef ENABLE_IPV6
else
port = ntohs(((struct sockaddr_in6 *)&add)->sin6_port);
#endif
infof(data, "Local port: %d\n", port);
return CURLE_OK;
}
if(--portnum > 0) {
infof(data, "Bind to local port %d failed, trying next\n", port);
port++; /* try next port */
}
else
break;
} while(1);
data->state.os_errno = Curl_sockerrno();
failf(data, "bind failure: %s",
Curl_strerror(conn, data->state.os_errno));
return CURLE_HTTP_PORT_FAILED;
}
/*
@ -405,15 +421,10 @@ static CURLcode bindlocal(struct connectdata *conn,
*/
static bool verifyconnect(curl_socket_t sockfd, int *error)
{
bool rc;
bool rc = TRUE;
#ifdef SO_ERROR
int err = 0;
#ifdef __hpux
int errSize = sizeof(err);
#else
socklen_t errSize = sizeof(err);
#endif
#ifdef WIN32
/*
@ -431,12 +442,24 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
*
* Someone got to verify this on Win-NT 4.0, 2000."
*/
#ifdef _WIN32_WCE
Sleep(0);
#else
SleepEx(0, FALSE);
#endif
#endif
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
(void *)&err, &errSize))
err = Curl_ourerrno();
err = Curl_sockerrno();
#ifdef _WIN32_WCE
/* Always returns this error, bug in CE? */
if(WSAENOPROTOOPT==err)
err=0;
#endif
if ((0 == err) || (EISCONN == err))
/* we are connected, awesome! */
@ -449,11 +472,30 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
#else
(void)sockfd;
if (error)
*error = Curl_ourerrno();
*error = Curl_sockerrno();
#endif
return rc;
}
CURLcode Curl_store_ip_addr(struct connectdata *conn)
{
char addrbuf[256];
Curl_printable_address(conn->ip_addr, addrbuf, sizeof(addrbuf));
/* save the string */
Curl_safefree(conn->ip_addr_str);
conn->ip_addr_str = strdup(addrbuf);
if(!conn->ip_addr_str)
return CURLE_OUT_OF_MEMORY; /* FAIL */
#ifdef PF_INET6
if(conn->ip_addr->ai_family == PF_INET6)
conn->bits.ipv6 = TRUE;
#endif
return CURLE_OK;
}
/* Used within the multi interface. Try next IP address, return TRUE if no
more address exists */
static bool trynextip(struct connectdata *conn,
@ -463,6 +505,11 @@ static bool trynextip(struct connectdata *conn,
curl_socket_t sockfd;
Curl_addrinfo *ai;
/* first close the failed socket */
sclose(conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
*connected = FALSE;
if(sockindex != FIRSTSOCKET)
return TRUE; /* no next */
@ -475,6 +522,8 @@ static bool trynextip(struct connectdata *conn,
/* store the new socket descriptor */
conn->sock[sockindex] = sockfd;
conn->ip_addr = ai;
Curl_store_ip_addr(conn);
return FALSE;
}
ai = ai->ai_next;
@ -496,6 +545,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
CURLcode code = CURLE_OK;
curl_socket_t sockfd = conn->sock[sockindex];
long allow = DEFAULT_CONNECT_TIMEOUT;
long allow_total = 0;
long has_passed;
curlassert(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
@ -503,17 +553,17 @@ CURLcode Curl_is_connected(struct connectdata *conn,
*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);
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
/* 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;
allow_total = allow = data->set.timeout*1000;
else
allow = data->set.connecttimeout*1000;
}
else if(data->set.timeout) {
allow = data->set.timeout*1000;
allow_total = allow = data->set.timeout*1000;
}
else if(data->set.connecttimeout) {
allow = data->set.connecttimeout*1000;
@ -526,30 +576,45 @@ CURLcode Curl_is_connected(struct connectdata *conn,
}
if(conn->bits.tcpconnect) {
/* we are connected already! */
Curl_expire(data, allow_total);
*connected = TRUE;
return CURLE_OK;
}
Curl_expire(data, allow);
/* check for connect without timeout as we want to return immediately */
rc = waitconnect(sockfd, 0);
if(WAITCONN_CONNECTED == rc) {
if (verifyconnect(sockfd, NULL)) {
int error;
if (verifyconnect(sockfd, &error)) {
/* we are connected, awesome! */
*connected = TRUE;
return CURLE_OK;
}
/* nope, not connected for real */
data->state.os_errno = error;
infof(data, "Connection failed\n");
if(trynextip(conn, sockindex, connected)) {
code = CURLE_COULDNT_CONNECT;
}
}
else if(WAITCONN_TIMEOUT != rc) {
int error = 0;
/* nope, not connected */
infof(data, "Connection failed\n");
if (WAITCONN_FDSET_ERROR == rc) {
(void)verifyconnect(sockfd, &error);
data->state.os_errno = error;
infof(data, "%s\n",Curl_strerror(conn,error));
}
else
infof(data, "Connection failed\n");
if(trynextip(conn, sockindex, connected)) {
int error = Curl_ourerrno();
error = Curl_sockerrno();
data->state.os_errno = error;
failf(data, "Failed connect to %s:%d; %s",
conn->host.name, conn->port, Curl_strerror(conn,error));
code = CURLE_COULDNT_CONNECT;
@ -569,10 +634,18 @@ static void tcpnodelay(struct connectdata *conn,
#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,
int proto = IPPROTO_TCP;
#ifdef HAVE_GETPROTOBYNAME
struct protoent *pe = getprotobyname("tcp");
if (pe)
proto = pe->p_proto;
#endif
if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set TCP_NODELAY: %s\n",
Curl_strerror(conn, Curl_ourerrno()));
Curl_strerror(conn, Curl_sockerrno()));
else
infof(data,"TCP_NODELAY set\n");
#else
@ -581,21 +654,42 @@ static void tcpnodelay(struct connectdata *conn,
#endif
}
#ifdef SO_NOSIGPIPE
/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
sending data to a dead peer (instead of relying on the 4th argument to send
being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
systems? */
static void nosigpipe(struct connectdata *conn,
curl_socket_t sockfd)
{
struct SessionHandle *data= conn->data;
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0)
infof(data, "Could not set SO_NOSIGPIPE: %s\n",
Curl_strerror(conn, Curl_sockerrno()));
}
#else
#define nosigpipe(x,y)
#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,
const Curl_addrinfo *ai,
long timeout_ms,
bool *connected)
{
char addr_buf[128];
int rc;
int error;
bool conected;
bool isconnected;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
curl_socket_t sockfd;
CURLcode res;
sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol);
if (sockfd == CURL_SOCKET_BAD)
return CURL_SOCKET_BAD;
@ -607,21 +701,37 @@ singleipconnect(struct connectdata *conn,
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;
nosigpipe(conn, sockfd);
if(data->set.fsockopt) {
/* activate callback for setting socket options */
error = data->set.fsockopt(data->set.sockopt_client,
sockfd,
CURLSOCKTYPE_IPCXN);
if (error) {
sclose(sockfd); /* close the socket and bail out */
return CURL_SOCKET_BAD;
}
}
/* possibly bind the local end to an IP, interface or port */
res = bindlocal(conn, sockfd);
if(res) {
sclose(sockfd); /* close socket and bail out */
return CURL_SOCKET_BAD;
}
/* set socket non-blocking */
Curl_nonblock(sockfd, TRUE);
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
/* Connect TCP sockets, bind UDP */
if(conn->socktype == SOCK_STREAM)
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
else
rc = 0;
if(-1 == rc) {
error = Curl_ourerrno();
error = Curl_sockerrno();
switch (error) {
case EINPROGRESS:
@ -639,6 +749,7 @@ singleipconnect(struct connectdata *conn,
/* unknown error, fallthrough and try another address! */
failf(data, "Failed to connect to %s: %s",
addr_buf, Curl_strerror(conn,error));
data->state.os_errno = error;
break;
}
}
@ -651,9 +762,9 @@ singleipconnect(struct connectdata *conn,
return sockfd;
}
conected = verifyconnect(sockfd, &error);
isconnected = verifyconnect(sockfd, &error);
if(!rc && conected) {
if(!rc && isconnected) {
/* we are connected, awesome! */
*connected = TRUE; /* this is a true connect */
infof(data, "connected\n");
@ -661,8 +772,10 @@ singleipconnect(struct connectdata *conn,
}
else if(WAITCONN_TIMEOUT == rc)
infof(data, "Timeout\n");
else
else {
data->state.os_errno = error;
infof(data, "%s\n", Curl_strerror(conn, error));
}
/* connect failed or timed out */
sclose(sockfd);
@ -677,7 +790,7 @@ singleipconnect(struct connectdata *conn,
*/
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
struct Curl_dns_entry *remotehost, /* use this one */
const 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? */
@ -704,7 +817,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
long has_passed;
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.start);
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
@ -731,6 +844,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
return CURLE_OPERATION_TIMEOUTED;
}
}
Curl_expire(data, timeout_ms);
/* Max time for each address */
num_addr = Curl_num_addresses(remotehost->addr);
@ -744,7 +858,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if(data->state.used_interface == Curl_if_multi)
/* don't hang when doing multi */
timeout_per_addr = timeout_ms = 0;
timeout_per_addr = 0;
/*
* Connecting with a Curl_addrinfo chain
@ -771,6 +885,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if (sockfd == CURL_SOCKET_BAD) {
/* no good connect was made */
*sockconn = CURL_SOCKET_BAD;
failf(data, "couldn't connect to host");
return CURLE_COULDNT_CONNECT;
}
@ -784,5 +899,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
if(sockconn)
*sockconn = sockfd; /* the socket descriptor we've connected */
data->info.numconnects++; /* to track the number of connections made */
return CURLE_OK;
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -31,13 +31,15 @@ CURLcode Curl_is_connected(struct connectdata *conn,
bool *connected);
CURLcode Curl_connecthost(struct connectdata *conn,
struct Curl_dns_entry *host, /* connect to this */
const 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);
int Curl_sockerrno(void);
CURLcode Curl_store_ip_addr(struct connectdata *conn);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -32,10 +32,14 @@
#include <curl/curl.h>
#include "sendf.h"
#include "content_encoding.h"
#include "curl_memory.h"
#include "memory.h"
#include "memdebug.h"
/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
(doing so will reduce code size slightly). */
#define OLD_ZLIB_SUPPORT 1
#define DSIZ 0x10000 /* buffer size for decompressed data */
#define GZIP_MAGIC_0 0x1f
@ -49,14 +53,23 @@
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
enum zlibState {
ZLIB_UNINIT, /* uninitialized */
ZLIB_INIT, /* initialized */
ZLIB_GZIP_HEADER, /* reading gzip header */
ZLIB_GZIP_INFLATING, /* inflating gzip stream */
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
};
static CURLcode
process_zlib_error(struct SessionHandle *data, z_stream *z)
process_zlib_error(struct connectdata *conn, z_stream *z)
{
struct SessionHandle *data = conn->data;
if (z->msg)
failf (data, "Error while processing content unencoding.\n%s",
failf (data, "Error while processing content unencoding: %s",
z->msg);
else
failf (data, "Error while processing content unencoding.\n"
failf (data, "Error while processing content unencoding: "
"Unknown failure within decompression software.");
return CURLE_BAD_CONTENT_ENCODING;
@ -66,71 +79,113 @@ static CURLcode
exit_zlib(z_stream *z, bool *zlib_init, CURLcode result)
{
inflateEnd(z);
*zlib_init = 0;
*zlib_init = ZLIB_UNINIT;
return result;
}
static CURLcode
inflate_stream(struct connectdata *conn,
struct Curl_transfer_keeper *k)
{
int allow_restart = 1;
z_stream *z = &k->z; /* zlib state structure */
uInt nread = z->avail_in;
Bytef *orig_in = z->next_in;
int status; /* zlib status */
CURLcode result = CURLE_OK; /* Curl_client_write status */
char *decomp; /* Put the decompressed data here. */
/* Dynamically allocate a buffer for decompression because it's uncommonly
large to hold on the stack */
decomp = (char*)malloc(DSIZ);
if (decomp == NULL) {
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* 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;
z->avail_out = DSIZ;
status = inflate(z, Z_SYNC_FLUSH);
if (status == Z_OK || status == Z_STREAM_END) {
allow_restart = 0;
if(DSIZ - z->avail_out) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp,
DSIZ - z->avail_out);
/* if !CURLE_OK, clean up, return */
if (result) {
free(decomp);
return exit_zlib(z, &k->zlib_init, result);
}
}
/* Done? clean up, return */
if (status == Z_STREAM_END) {
free(decomp);
if (inflateEnd(z) == Z_OK)
return exit_zlib(z, &k->zlib_init, result);
else
return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
}
/* Done with these bytes, exit */
if (status == Z_OK && z->avail_in == 0) {
free(decomp);
return result;
}
}
else if (allow_restart && status == Z_DATA_ERROR) {
/* some servers seem to not generate zlib headers, so this is an attempt
to fix and continue anyway */
inflateReset(z);
if (inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(conn, z);
}
z->next_in = orig_in;
z->avail_in = nread;
allow_restart = 0;
continue;
}
else { /* Error; exit loop, handle below */
free(decomp);
return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
}
}
/* Will never get here */
}
CURLcode
Curl_unencode_deflate_write(struct SessionHandle *data,
Curl_unencode_deflate_write(struct connectdata *conn,
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) {
if (k->zlib_init == ZLIB_UNINIT) {
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;
return process_zlib_error(conn, z);
k->zlib_init = ZLIB_INIT;
}
/* 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));
}
}
/* Now uncompress the data */
return inflate_stream(conn, k);
}
#ifdef OLD_ZLIB_SUPPORT
/* Skip over the gzip header */
static enum {
GZIP_OK,
@ -172,6 +227,7 @@ static enum {
return GZIP_UNDERFLOW;
len -= (extra_len + 2);
data += (extra_len + 2);
}
if (flags & ORIG_NAME) {
@ -213,38 +269,67 @@ static enum {
*headerlen = totallen - len;
return GZIP_OK;
}
#endif
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
Curl_unencode_gzip_write(struct connectdata *conn,
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) {
if (k->zlib_init == ZLIB_UNINIT) {
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 */
if (strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if (inflateInit2(z, MAX_WBITS+32) != Z_OK) {
return process_zlib_error(conn, z);
}
k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
} else {
/* we must parse the gzip header ourselves */
if (inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(conn, z);
}
k->zlib_init = ZLIB_INIT; /* Initial call state */
}
}
if (k->zlib_init == ZLIB_INIT_GZIP) {
/* Let zlib handle the gzip decompression entirely */
z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)nread;
/* Now uncompress the data */
return inflate_stream(conn, k);
}
#ifndef OLD_ZLIB_SUPPORT
/* Support for old zlib versions is compiled away and we are running with
an old version, so return an error. */
return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND);
#else
/* 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.
*
* This is only required with zlib versions < 1.2.0.4 as newer versions
* can handle the gzip header themselves.
*/
switch (k->zlib_init) {
/* Skip over gzip header? */
if (k->zlib_init == 1) {
case ZLIB_INIT:
{
/* Initial call state */
ssize_t hlen;
@ -252,7 +337,7 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
case GZIP_OK:
z->next_in = (Bytef *)k->str + hlen;
z->avail_in = (uInt)(nread - hlen);
k->zlib_init = 3; /* Inflating stream state */
k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
@ -269,17 +354,20 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
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 */
k->zlib_init = ZLIB_GZIP_HEADER; /* 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));
return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
}
}
else if (k->zlib_init == 2) {
break;
case ZLIB_GZIP_HEADER:
{
/* Need more gzip header data state */
ssize_t hlen;
unsigned char *oldblock = z->next_in;
@ -300,7 +388,7 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
/* 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 */
k->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
@ -310,14 +398,18 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
case GZIP_BAD:
default:
free(z->next_in);
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
return exit_zlib(z, &k->zlib_init, process_zlib_error(conn, z));
}
}
else {
break;
case ZLIB_GZIP_INFLATING:
default:
/* Inflating stream state */
z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)nread;
break;
}
if (z->avail_in == 0) {
@ -325,39 +417,8 @@ Curl_unencode_gzip_write(struct SessionHandle *data,
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));
}
}
/* We've parsed the header, now uncompress the data */
return inflate_stream(conn, k);
#endif
}
#endif /* HAVE_LIBZ */

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -31,11 +31,11 @@
#define ALL_CONTENT_ENCODINGS "identity"
#endif
CURLcode Curl_unencode_deflate_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
CURLcode Curl_unencode_deflate_write(struct connectdata *conn,
struct Curl_transfer_keeper *k,
ssize_t nread);
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
Curl_unencode_gzip_write(struct connectdata *conn,
struct Curl_transfer_keeper *k,
ssize_t nread);

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -80,25 +80,30 @@ Example set of cookies:
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define _MPRINTF_REPLACE /* without this on windows OS we get undefined reference to snprintf */
#include <curl/mprintf.h>
#include "urldata.h"
#include "cookie.h"
#include "getdate.h"
#include "strequal.h"
#include "strtok.h"
#include "sendf.h"
#include "curl_memory.h"
#include "memory.h"
#include "share.h"
#include "strtoofft.h"
/* The last #include file should be: */
#ifdef CURLDEBUG
#include "memdebug.h"
#endif
#define my_isspace(x) ((x == ' ') || (x == '\t'))
static void freecookie(struct Cookie *co)
{
if(co->expirestr)
@ -111,6 +116,10 @@ static void freecookie(struct Cookie *co)
free(co->name);
if(co->value)
free(co->value);
if(co->maxage)
free(co->maxage);
if(co->version)
free(co->version);
free(co);
}
@ -126,6 +135,27 @@ static bool tailmatch(const char *little, const char *bigone)
return (bool)strequal(little, bigone+biglen-littlelen);
}
/*
* Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
*/
void Curl_cookie_loadfiles(struct SessionHandle *data)
{
struct curl_slist *list = data->change.cookielist;
if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) {
data->cookies = Curl_cookie_init(data,
list->data,
data->cookies,
data->set.cookiesession);
list = list->next;
}
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
curl_slist_free_all(data->change.cookielist); /* clean up list */
data->change.cookielist = NULL; /* don't do this again! */
}
}
/****************************************************************************
*
* Curl_cookie_add()
@ -156,7 +186,7 @@ Curl_cookie_add(struct SessionHandle *data,
struct Cookie *co;
struct Cookie *lastc=NULL;
time_t now = time(NULL);
bool replace_old;
bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
/* First, alloc and init a new struct for it */
@ -176,7 +206,7 @@ Curl_cookie_add(struct SessionHandle *data,
semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
while(*lineptr && isspace((int)*lineptr))
while(*lineptr && my_isspace(*lineptr))
lineptr++;
ptr = lineptr;
@ -199,14 +229,14 @@ Curl_cookie_add(struct SessionHandle *data,
/* Strip off trailing whitespace from the 'what' */
size_t len=strlen(what);
while(len && isspace((int)what[len-1])) {
while(len && my_isspace(what[len-1])) {
what[len-1]=0;
len--;
}
/* Skip leading whitespace from the 'what' */
whatptr=what;
while(isspace((int)*whatptr)) {
while(my_isspace(*whatptr)) {
whatptr++;
}
@ -305,7 +335,7 @@ Curl_cookie_add(struct SessionHandle *data,
break;
}
co->expires =
atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now;
atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + (long)now;
}
else if(strequal("expires", name)) {
co->expirestr=strdup(whatptr);
@ -348,7 +378,7 @@ Curl_cookie_add(struct SessionHandle *data,
}
ptr=semiptr+1;
while(ptr && *ptr && isspace((int)*ptr))
while(ptr && *ptr && my_isspace(*ptr))
ptr++;
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
@ -466,7 +496,7 @@ Curl_cookie_add(struct SessionHandle *data,
co->secure = (bool)strequal(ptr, "TRUE");
break;
case 4:
co->expires = atoi(ptr);
co->expires = curlx_strtoofft(ptr, NULL, 10);
break;
case 5:
co->name = strdup(ptr);
@ -647,6 +677,10 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
fp = stdin;
fromfile=FALSE;
}
else if(file && !*file) {
/* points to a "" string */
fp = NULL;
}
else
fp = file?fopen(file, "r"):NULL;
@ -668,7 +702,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
lineptr=line;
headerline=FALSE;
}
while(*lineptr && isspace((int)*lineptr))
while(*lineptr && my_isspace(*lineptr))
lineptr++;
Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
@ -699,68 +733,85 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
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;
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 */
if(!c || !c->cookies)
return NULL; /* no cookie struct or no cookies in the struct */
co = c->cookies;
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) ) {
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 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) ) {
/* now check the left part of the path with the cookies path
requirement */
if(!co->path ||
/* not using checkprefix() because matching should be
case-sensitive */
!strncmp(co->path, path, strlen(co->path)) ) {
/* and now, we know this is a match and we should create an
entry for the return-linked-list */
/* 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));
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;
/* 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;
}
/* 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 NULL;
}
}
}
}
co = co->next;
}
return mainco; /* return the new list */
return mainco; /* return the new list */
}
/*****************************************************************************
*
* Curl_cookie_clearall()
*
* Clear all existing cookies and reset the counter.
*
****************************************************************************/
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
Curl_cookie_freelist(cookies->cookies);
cookies->cookies = NULL;
cookies->numcookies = 0;
}
}
/*****************************************************************************
*
@ -772,17 +823,56 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
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
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;
}
}
co = next;
}
}
}
/*****************************************************************************
*
* Curl_cookie_clearsess()
*
* Free all session cookies in the cookies list.
*
****************************************************************************/
void Curl_cookie_clearsess(struct CookieInfo *cookies)
{
struct Cookie *first, *curr, *next, *prev = NULL;
if(!cookies->cookies)
return;
first = curr = prev = cookies->cookies;
for(; curr; curr = next) {
next = curr->next;
if(!curr->expires) {
if(first == curr)
first = next;
if(prev == curr)
prev = next;
else
prev->next = next;
free(curr);
cookies->numcookies--;
}
else
prev = curr;
}
cookies->cookies = first;
}
/*****************************************************************************
*
* Curl_cookie_cleanup()
@ -792,20 +882,48 @@ void Curl_cookie_freelist(struct Cookie *co)
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
struct Cookie *co;
struct Cookie *next;
if(c) {
if(c->filename)
free(c->filename);
co = c->cookies;
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 */
}
while(co) {
next = co->next;
freecookie(co);
co = next;
}
free(c); /* free the base struct as well */
}
}
/* get_netscape_format()
*
* Formats a string for Netscape output file, w/o a newline at the end.
*
* Function returns a char * to a formatted line. Has to be free()d
*/
static char *get_netscape_format(const struct Cookie *co)
{
return aprintf(
"%s%s\t" /* domain */
"%s\t" /* tailmatch */
"%s\t" /* path */
"%s\t" /* secure */
"%" FORMAT_OFF_T "\t" /* expires */
"%s\t" /* name */
"%s", /* 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",
co->expires,
co->name,
co->value?co->value:"");
}
/*
@ -839,33 +957,22 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
}
if(c) {
char *format_ptr;
fputs("# Netscape HTTP Cookie File\n"
"# http://www.netscape.com/newsref/std/cookie_spec.html\n"
"# http://curlm.haxx.se/rfc/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:"");
format_ptr = get_netscape_format(co);
if (format_ptr == NULL) {
fprintf(out, "#\n# Fatal libcurl error\n");
return 1;
}
fprintf(out, "%s\n", format_ptr);
free(format_ptr);
co=co->next;
}
}
@ -876,4 +983,35 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
return 0;
}
#endif /* CURL_DISABLE_HTTP */
struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
{
struct curl_slist *list = NULL;
struct curl_slist *beg;
struct Cookie *c;
char *line;
if ((data->cookies == NULL) ||
(data->cookies->numcookies == 0))
return NULL;
c = data->cookies->cookies;
beg = list;
while (c) {
/* fill the list with _all_ the cookies we know */
line = get_netscape_format(c);
if (line == NULL) {
/* get_netscape_format returns null only if we run out of memory */
curl_slist_free_all(beg); /* free some memory */
return NULL;
}
list = curl_slist_append(list, line);
free(line);
c = c->next;
}
return list;
}
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -24,11 +24,13 @@
***************************************************************************/
#include <stdio.h>
#ifdef WIN32
#if defined(WIN32)
#include <time.h>
#else
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#endif
#include <curl/curl.h>
@ -38,7 +40,7 @@ struct Cookie {
char *value; /* name = <this> */
char *path; /* path = <this> */
char *domain; /* domain = <this> */
long expires; /* expires = <this> */
curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */
bool tailmatch; /* weather we do tail-matchning of the domain name */
@ -89,7 +91,17 @@ 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_clearall(struct CookieInfo *cookies);
void Curl_cookie_clearsess(struct CookieInfo *cookies);
void Curl_cookie_cleanup(struct CookieInfo *);
int Curl_cookie_output(struct CookieInfo *, char *);
#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES)
#define Curl_cookie_list(x) NULL
#define Curl_cookie_loadfiles(x) do { } while (0)
#else
struct curl_slist *Curl_cookie_list(struct SessionHandle *data);
void Curl_cookie_loadfiles(struct SessionHandle *data);
#endif
#endif

View File

@ -4,7 +4,7 @@ It was downloaded from http://curl.haxx.se
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2004, Daniel Stenberg, <daniel@haxx.se>.
Copyright (c) 1996 - 2007, Daniel Stenberg, <daniel@haxx.se>.
All rights reserved.

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -47,16 +47,49 @@ typedef void CURL;
extern "C" {
#endif
/*
* Decorate exportable functions for Win32 DLL linking.
* This avoids using a .def file for building libcurl.dll.
*/
#if (defined(WIN32) || defined(_WIN32)) && !defined(CURL_STATICLIB)
#if defined(BUILDING_LIBCURL)
#define CURL_EXTERN __declspec(dllexport)
#else
#define CURL_EXTERN __declspec(dllimport)
#endif
#else
#ifdef CURL_HIDDEN_SYMBOLS
/*
* This definition is used to make external definitions visibile in the
* shared library when symbols are hidden by default. It makes no
* difference when compiling applications whether this is set or not,
* only when compiling the library.
*/
#define CURL_EXTERN CURL_EXTERN_SYMBOL
#else
#define CURL_EXTERN
#endif
#endif
/*
* We want the typedef curl_off_t setup for large file support on all
* platforms. We also provide a CURL_FORMAT_OFF_T define to use in *printf
* format strings when outputting a variable of type curl_off_t.
*
* Note: "pocc -Ze" is MSVC compatibily mode and this sets _MSC_VER!
*/
#if defined(_MSC_VER) || defined(__LCC__)
#if (defined(_MSC_VER) && !defined(__POCC__)) || (defined(__LCC__) && defined(WIN32))
/* MSVC */
#ifdef _WIN32_WCE
typedef long curl_off_t;
#define CURL_FORMAT_OFF_T "%ld"
#else
typedef signed __int64 curl_off_t;
#define CURL_FORMAT_OFF_T "%I64d"
#else /* _MSC_VER || __LCC__ */
#endif
#else /* (_MSC_VER && !__POCC__) || (__LCC__ && WIN32) */
#if (defined(__GNUC__) && defined(WIN32)) || defined(__WATCOMC__)
/* gcc on windows or Watcom */
typedef long long curl_off_t;
@ -88,7 +121,7 @@ extern "C" {
#define CURL_FORMAT_OFF_T "%ld"
#endif
#endif /* GCC or Watcom on Windows */
#endif /* _MSC_VER || __LCC__ */
#endif /* (_MSC_VER && !__POCC__) || (__LCC__ && WIN32) */
#ifdef UNDEF_FILE_OFFSET_BITS
/* this was defined above for our checks, undefine it again */
@ -100,6 +133,49 @@ extern "C" {
#undef FILESIZEBITS
#endif
#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(_WIN32_WCE) && !defined(__GNUC__) && \
!defined(__CYGWIN__) || defined(__MINGW32__)
#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H))
/* The check above prevents the winsock2 inclusion if winsock.h already was
included, since they can't co-exist without problems */
#include <winsock2.h>
#endif
#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) || defined(__NetBSD__) || defined(__minix)
#include <sys/select.h>
#endif
#ifndef _WIN32_WCE
#include <sys/socket.h>
#endif
#ifndef __WATCOMC__
#include <sys/time.h>
#endif
#include <sys/types.h>
#endif
#ifndef curl_socket_typedef
/* socket typedef */
#ifdef WIN32
typedef SOCKET curl_socket_t;
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
typedef int curl_socket_t;
#define CURL_SOCKET_BAD -1
#endif
#define curl_socket_typedef
#endif /* curl_socket_typedef */
struct curl_httppost {
struct curl_httppost *next; /* next entry in the list */
char *name; /* pointer to allocated name */
@ -143,19 +219,47 @@ typedef size_t (*curl_write_callback)(char *buffer,
size_t nitems,
void *outstream);
/* This is a brand new return code for the read callback that will signal
the caller to immediately abort the current transfer. */
/* This is a return code for the read callback that, when returned, will
signal libcurl to immediately abort the current transfer. */
#define CURL_READFUNC_ABORT 0x10000000
typedef size_t (*curl_read_callback)(char *buffer,
size_t size,
size_t nitems,
void *instream);
size_t size,
size_t nitems,
void *instream);
typedef enum {
CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
CURLSOCKTYPE_LAST /* never use */
} curlsocktype;
typedef int (*curl_sockopt_callback)(void *clientp,
curl_socket_t curlfd,
curlsocktype purpose);
#ifndef CURL_NO_OLDIES
/* not used since 7.10.8, will be removed in a future release */
typedef int (*curl_passwd_callback)(void *clientp,
const char *prompt,
char *buffer,
int buflen);
#endif
typedef enum {
CURLIOE_OK, /* I/O operation successful */
CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
CURLIOE_FAILRESTART, /* failed to restart the read */
CURLIOE_LAST /* never use */
} curlioerr;
typedef enum {
CURLIOCMD_NOP, /* no operation */
CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
CURLIOCMD_LAST /* never use */
} curliocmd;
typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
int cmd,
void *clientp);
/*
* The following typedef's are signatures of malloc, free, realloc, strdup and
@ -200,13 +304,15 @@ typedef enum {
CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
CURLE_FAILED_INIT, /* 2 */
CURLE_URL_MALFORMAT, /* 3 */
CURLE_URL_MALFORMAT_USER, /* 4 (NOT USED) */
CURLE_URL_MALFORMAT_USER, /* 4 - NOT USED */
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
CURLE_COULDNT_CONNECT, /* 7 */
CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
CURLE_FTP_ACCESS_DENIED, /* 9 */
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 */
CURLE_FTP_ACCESS_DENIED, /* 9 a service was denied by the FTP server
due to lack of access - when login fails
this is not returned. */
CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 - NOT USED */
CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
CURLE_FTP_WEIRD_USER_REPLY, /* 12 */
CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
@ -224,6 +330,10 @@ typedef enum {
CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */
CURLE_READ_ERROR, /* 26 - could open/read from file */
CURLE_OUT_OF_MEMORY, /* 27 */
/* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
instead of a memory allocation error if CURL_DOES_CONVERSIONS
is defined
*/
CURLE_OPERATION_TIMEOUTED, /* 28 - the timeout time was reached */
CURLE_FTP_COULDNT_SET_ASCII, /* 29 - TYPE A failed */
CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
@ -262,10 +372,39 @@ typedef enum {
CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
CURLE_FTP_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
that failed */
CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
accepted and we failed to login */
CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
CURLE_TFTP_PERM, /* 69 - permission problem on server */
CURLE_TFTP_DISKFULL, /* 70 - out of disk space on server */
CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
CURLE_TFTP_EXISTS, /* 73 - File already exists */
CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
CURLE_CONV_FAILED, /* 75 - conversion failed */
CURLE_CONV_REQD, /* 76 - caller must register conversion
callbacks using curl_easy_setopt options
CURLOPT_CONV_FROM_NETWORK_FUNCTION,
CURLOPT_CONV_TO_NETWORK_FUNCTION, and
CURLOPT_CONV_FROM_UTF8_FUNCTION */
CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
or wrong format */
CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
CURLE_SSH, /* 79 - error from the SSH layer, somewhat
generic so the error message will be of
interest when this has happened */
CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
connection */
CURL_LAST /* never use! */
} CURLcode;
/* This prototype applies to all conversion callbacks */
typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
void *ssl_ctx, /* actually an
OpenSSL SSL_CTX */
@ -274,9 +413,12 @@ typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */
/* Make a spelling correction for the operation timed-out define */
#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
/* backwards compatibility with older names */
#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
#endif
typedef enum {
CURLPROXY_HTTP = 0,
@ -292,17 +434,29 @@ typedef enum {
#define CURLAUTH_ANY ~0 /* all types set */
#define CURLAUTH_ANYSAFE (~CURLAUTH_BASIC)
#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */
#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */
#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */
#define CURLSSH_AUTH_HOST (1<<2) /* host key files */
#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */
#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
/* this was the error code 50 in 7.7.3 and a few earlier versions, this
is no longer used by libcurl but is instead #defined here only to not
make programs break */
#define CURLE_ALREADY_COMPLETE 99999
/* This is just to make older programs not break: */
/* These are just to make older programs not break: */
#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
#endif
#define CURL_ERROR_SIZE 256
/* parameter for the CURLOPT_FTP_SSL option */
typedef enum {
CURLFTPSSL_NONE, /* do not attempt to use SSL */
CURLFTPSSL_TRY, /* try using SSL, proceed anyway otherwise */
@ -311,6 +465,23 @@ typedef enum {
CURLFTPSSL_LAST /* not an option, never use */
} curl_ftpssl;
/* parameter for the CURLOPT_FTPSSLAUTH option */
typedef enum {
CURLFTPAUTH_DEFAULT, /* let libcurl decide */
CURLFTPAUTH_SSL, /* use "AUTH SSL" */
CURLFTPAUTH_TLS, /* use "AUTH TLS" */
CURLFTPAUTH_LAST /* not an option, never use */
} curl_ftpauth;
/* parameter for the CURLOPT_FTP_FILEMETHOD option */
typedef enum {
CURLFTPMETHOD_DEFAULT, /* let libcurl pick */
CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */
CURLFTPMETHOD_NOCWD, /* no CWD at all */
CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
CURLFTPMETHOD_LAST /* not an option, never use */
} curl_ftpmethod;
/* long may be 32 or 64 bits, but we should never depend on anything else
but 32 */
#define CURLOPTTYPE_LONG 0
@ -332,7 +503,8 @@ typedef enum {
* platforms.
*/
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__)
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__)
/* This compiler is believed to have an ISO compatible preprocessor */
#define CURL_ISOCPP
#else
@ -655,7 +827,7 @@ typedef enum {
CINIT(SSLENGINE_DEFAULT, LONG, 90),
/* Non-zero value means to use the global dns cache */
CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* To become OBSOLETE soon */
CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* To becomeO BSOLETE soon */
/* DNS cache timeout */
CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
@ -785,33 +957,102 @@ typedef enum {
/* Enable/disable the TCP Nagle algorithm */
CINIT(TCP_NODELAY, LONG, 121),
/* When doing 3rd party transfer, set the source host name with this */
CINIT(SOURCE_HOST, OBJECTPOINT, 122),
/* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
/* 123 OBSOLETE. Gone in 7.16.0 */
/* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
/* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
/* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
/* 127 OBSOLETE. Gone in 7.16.0 */
/* 128 OBSOLETE. Gone in 7.16.0 */
/* When doing 3rd party transfer, set the source user and password with
this */
CINIT(SOURCE_USERPWD, OBJECTPOINT, 123),
/* When FTP over SSL/TLS is selected (with CURLOPT_FTP_SSL), this option
can be used to change libcurl's default action which is to first try
"AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
response has been received.
/* When doing 3rd party transfer, set the source file path with this */
CINIT(SOURCE_PATH, OBJECTPOINT, 124),
Available parameters are:
CURLFTPAUTH_DEFAULT - let libcurl decide
CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS
CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL
*/
CINIT(FTPSSLAUTH, LONG, 129),
/* When doing 3rd party transfer, set the source server's port number
with this */
CINIT(SOURCE_PORT, LONG, 125),
CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
CINIT(IOCTLDATA, OBJECTPOINT, 131),
/* When doing 3rd party transfer, decide which server that should get the
PASV command (and the other gets the PORT).
0 (default) - The target host issues PASV.
1 - The source host issues PASV */
CINIT(PASV_HOST, LONG, 126),
/* 132 OBSOLETE. Gone in 7.16.0 */
/* 133 OBSOLETE. Gone in 7.16.0 */
/* When doing 3rd party transfer, set the source pre-quote linked list
of commands with this */
CINIT(SOURCE_PREQUOTE, OBJECTPOINT, 127),
/* zero terminated string for pass on to the FTP server when asked for
"account" info */
CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
/* When doing 3rd party transfer, set the source post-quote linked list
of commands with this */
CINIT(SOURCE_POSTQUOTE, OBJECTPOINT, 128),
/* feed cookies into cookie engine */
CINIT(COOKIELIST, OBJECTPOINT, 135),
/* ignore Content-Length */
CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
/* Set to non-zero to skip the IP address received in a 227 PASV FTP server
response. Typically used for FTP-SSL purposes but is not restricted to
that. libcurl will then instead use the same IP address it used for the
control connection. */
CINIT(FTP_SKIP_PASV_IP, LONG, 137),
/* Select "file method" to use when doing FTP, see the curl_ftpmethod
above. */
CINIT(FTP_FILEMETHOD, LONG, 138),
/* Local port number to bind the socket to */
CINIT(LOCALPORT, LONG, 139),
/* Number of ports to try, including the first one set with LOCALPORT.
Thus, setting it to 1 will make no additional attempts but the first.
*/
CINIT(LOCALPORTRANGE, LONG, 140),
/* no transfer, set up connection and let application use the socket by
extracting it with CURLINFO_LASTSOCKET */
CINIT(CONNECT_ONLY, LONG, 141),
/* Function that will be called to convert from the
network encoding (instead of using the iconv calls in libcurl) */
CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
/* Function that will be called to convert to the
network encoding (instead of using the iconv calls in libcurl) */
CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
/* Function that will be called to convert from UTF8
(instead of using the iconv calls in libcurl)
Note that this is used only for SSL certificate processing */
CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
/* if the connection proceeds too quickly then need to slow it down */
/* limit-rate: maximum number of bytes per second to send or receive */
CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
/* Pointer to command string to send if USER/PASS fails. */
CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
/* callback function for setting socket options */
CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
/* set to 0 to disable session ID re-use for this transfer, default is
enabled (== 1) */
CINIT(SSL_SESSIONID_CACHE, LONG, 150),
/* allowed SSH authentication methods */
CINIT(SSH_AUTH_TYPES, LONG, 151),
/* Used by scp/sftp to do public/private key authentication */
CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152),
CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153),
/* Send CCC (Clear Command Channel) after authentication */
CINIT(FTP_SSL_CCC, LONG, 154),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@ -831,13 +1072,6 @@ typedef enum {
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
#define CURLOPT_HTTPREQUEST -1
#define CURLOPT_FTPASCII CURLOPT_TRANSFERTEXT
#define CURLOPT_MUTE -2
#define CURLOPT_PASSWDFUNCTION -3
#define CURLOPT_PASSWDDATA -4
#define CURLOPT_CLOSEFUNCTION -5
#else
/* This is set if CURL_NO_OLDIES is defined at compile-time */
#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
@ -894,8 +1128,8 @@ typedef enum {
/* curl_strequal() and curl_strnequal() are subject for removal in a future
libcurl, see lib/README.curlx for details */
extern int (curl_strequal)(const char *s1, const char *s2);
extern int (curl_strnequal)(const char *s1, const char *s2, size_t n);
CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
/* name is uppercase CURLFORM_<name> */
#ifdef CFINIT
@ -941,8 +1175,8 @@ typedef enum {
/* structure to be used as parameter for CURLFORM_ARRAY */
struct curl_forms {
CURLformoption option;
const char *value;
CURLformoption option;
const char *value;
};
/* use this for multipart formpost building */
@ -984,10 +1218,30 @@ typedef enum {
* adds one part that together construct a full post. Then use
* CURLOPT_HTTPPOST to send it off to libcurl.
*/
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
...);
CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
...);
/*
* callback function for curl_formget()
* The void *arg pointer will be the one passed as second argument to curl_formget().
* The character buffer passed to it must not be freed.
* Should return the buffer length passed to it as the argument "len" on success.
*/
typedef size_t (*curl_formget_callback)(void *arg, const char *buf, size_t len);
/*
* NAME curl_formget()
*
* DESCRIPTION
*
* Serialize a curl_httppost struct built with curl_formadd().
* Accepts a void pointer as second argument which will be passed to
* the curl_formget_callback function.
* Returns 0 on success.
*/
CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
curl_formget_callback append);
/*
* NAME curl_formfree()
*
@ -995,7 +1249,7 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
*
* Free a multipart formpost previously built with curl_formadd().
*/
void curl_formfree(struct curl_httppost *form);
CURL_EXTERN void curl_formfree(struct curl_httppost *form);
/*
* NAME curl_getenv()
@ -1005,7 +1259,7 @@ void curl_formfree(struct curl_httppost *form);
* Returns a malloc()'ed string that MUST be curl_free()ed after usage is
* complete. DEPRECATED - see lib/README.curlx
*/
char *curl_getenv(const char *variable);
CURL_EXTERN char *curl_getenv(const char *variable);
/*
* NAME curl_version()
@ -1014,10 +1268,10 @@ char *curl_getenv(const char *variable);
*
* Returns a static ascii string of the libcurl version.
*/
char *curl_version(void);
CURL_EXTERN char *curl_version(void);
/*
* NAME curl_escape()
* NAME curl_easy_escape()
*
* DESCRIPTION
*
@ -1025,18 +1279,34 @@ char *curl_version(void);
* %XX versions). This function returns a new allocated string or NULL if an
* error occurred.
*/
char *curl_escape(const char *string, int length);
CURL_EXTERN char *curl_easy_escape(CURL *handle,
const char *string,
int length);
/* the previous version: */
CURL_EXTERN char *curl_escape(const char *string,
int length);
/*
* NAME curl_unescape()
* NAME curl_easy_unescape()
*
* DESCRIPTION
*
* Unescapes URL encoding in strings (converts all %XX codes to their 8bit
* versions). This function returns a new allocated string or NULL if an error
* occurred.
* Conversion Note: On non-ASCII platforms the ASCII %XX codes are
* converted into the host encoding.
*/
char *curl_unescape(const char *string, int length);
CURL_EXTERN char *curl_easy_unescape(CURL *handle,
const char *string,
int length,
int *outlength);
/* the previous version */
CURL_EXTERN char *curl_unescape(const char *string,
int length);
/*
* NAME curl_free()
@ -1046,7 +1316,7 @@ char *curl_unescape(const char *string, int length);
* Provided for de-allocation in the same translation unit that did the
* allocation. Added in libcurl 7.10
*/
void curl_free(void *p);
CURL_EXTERN void curl_free(void *p);
/*
* NAME curl_global_init()
@ -1056,7 +1326,7 @@ void curl_free(void *p);
* curl_global_init() should be invoked exactly once for each application that
* uses libcurl
*/
CURLcode curl_global_init(long flags);
CURL_EXTERN CURLcode curl_global_init(long flags);
/*
* NAME curl_global_init_mem()
@ -1071,12 +1341,12 @@ CURLcode curl_global_init(long flags);
* callback routines with be invoked by this library instead of the system
* memory management routines like malloc, free etc.
*/
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);
CURL_EXTERN 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);
/*
* NAME curl_global_cleanup()
@ -1086,7 +1356,7 @@ CURLcode curl_global_init_mem(long flags,
* curl_global_cleanup() should be invoked exactly once for each application
* that uses libcurl
*/
void curl_global_cleanup(void);
CURL_EXTERN void curl_global_cleanup(void);
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist {
@ -1102,7 +1372,8 @@ struct curl_slist {
* Appends a string to a linked list. If no list exists, it will be created
* first. Returns the new list, after appending.
*/
struct curl_slist *curl_slist_append(struct curl_slist *, const char *);
CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
const char *);
/*
* NAME curl_slist_free_all()
@ -1111,7 +1382,7 @@ struct curl_slist *curl_slist_append(struct curl_slist *, const char *);
*
* free a previously built curl_slist.
*/
void curl_slist_free_all(struct curl_slist *);
CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
/*
* NAME curl_getdate()
@ -1119,15 +1390,15 @@ void curl_slist_free_all(struct curl_slist *);
* DESCRIPTION
*
* Returns the time, in seconds since 1 Jan 1970 of the time string given in
* the first argument. The time argument in the second parameter is for cases
* where the specified time is relative now, like 'two weeks' or 'tomorrow'
* etc.
* the first argument. The time argument in the second parameter is unused
* and should be set to NULL.
*/
time_t curl_getdate(const char *p, const time_t *now);
CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
#define CURLINFO_STRING 0x100000
#define CURLINFO_LONG 0x200000
#define CURLINFO_DOUBLE 0x300000
#define CURLINFO_SLIST 0x400000
#define CURLINFO_MASK 0x0fffff
#define CURLINFO_TYPEMASK 0xf00000
@ -1157,9 +1428,15 @@ typedef enum {
CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22,
CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23,
CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24,
CURLINFO_OS_ERRNO = CURLINFO_LONG + 25,
CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
/* Fill in new entries below here! */
CURLINFO_LASTONE = 23
CURLINFO_LASTONE = 30
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@ -1242,9 +1519,9 @@ typedef enum {
CURLSHOPT_LAST /* never use */
} CURLSHoption;
CURLSH *curl_share_init(void);
CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
CURLSHcode curl_share_cleanup(CURLSH *);
CURL_EXTERN CURLSH *curl_share_init(void);
CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
/****************************************************************************
* Structures for querying information about the curl library at runtime.
@ -1254,15 +1531,16 @@ typedef enum {
CURLVERSION_FIRST,
CURLVERSION_SECOND,
CURLVERSION_THIRD,
CURLVERSION_FOURTH,
CURLVERSION_LAST /* never actually use this */
} CURLversion;
/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
basicly all programs ever, that want to get version information. It is
meant to be a built-in version number for what kind of struct the caller
expects. If the struct ever changes, we redfine the NOW to another enum
expects. If the struct ever changes, we redefine the NOW to another enum
from above. */
#define CURLVERSION_NOW CURLVERSION_THIRD
#define CURLVERSION_NOW CURLVERSION_FOURTH
typedef struct {
CURLversion age; /* age of the returned struct */
@ -1270,18 +1548,26 @@ typedef struct {
unsigned int version_num; /* LIBCURL_VERSION_NUM */
const char *host; /* OS/host/cpu/machine when configured */
int features; /* bitmask, see defines below */
char *ssl_version; /* human readable string */
long ssl_version_num; /* number */
const char *libz_version; /* human readable string */
const char *ssl_version; /* human readable string */
long ssl_version_num; /* not used anymore, always 0 */
const char *libz_version; /* human readable string */
/* protocols is terminated by an entry with a NULL protoname */
const char **protocols;
const char * const *protocols;
/* The fields below this were added in CURLVERSION_SECOND */
const char *ares;
int ares_num;
/* This field was aded in CURLVERSION_THIRD */
/* This field was added in CURLVERSION_THIRD */
const char *libidn;
/* These field were added in CURLVERSION_FOURTH */
/* Same as '_libiconv_version' if built with HAVE_ICONV */
int iconv_ver_num;
const char *libssh_version; /* human readable string */
} curl_version_info_data;
#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
@ -1295,6 +1581,9 @@ typedef struct {
#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth */
#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */
#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */
#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */
#define CURL_VERSION_CONV (1<<12) /* character conversions are
supported */
/*
* NAME curl_version_info()
@ -1304,7 +1593,7 @@ typedef struct {
* This function returns a pointer to a static copy of the version info
* struct. See above.
*/
curl_version_info_data *curl_version_info(CURLversion);
CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
/*
* NAME curl_easy_strerror()
@ -1315,7 +1604,7 @@ curl_version_info_data *curl_version_info(CURLversion);
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
const char *curl_easy_strerror(CURLcode);
CURL_EXTERN const char *curl_easy_strerror(CURLcode);
/*
* NAME curl_share_strerror()
@ -1326,7 +1615,7 @@ const char *curl_easy_strerror(CURLcode);
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
const char *curl_share_strerror(CURLSHcode);
CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
#ifdef __cplusplus
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -28,7 +28,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.12.1"
#define LIBCURL_VERSION "7.16.1"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 16
#define LIBCURL_VERSION_PATCH 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
@ -37,19 +43,14 @@
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".
hexadecimal (using 8 bits each). 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.
This 6-digit (24 bits) 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
#define LIBCURL_VERSION_NUM 0x071001
#endif /* __CURL_CURLVER_H */

View File

@ -26,10 +26,10 @@
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);
CURL_EXTERN CURL *curl_easy_init(void);
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
/*
* NAME curl_easy_getinfo()
@ -44,7 +44,7 @@ void curl_easy_cleanup(CURL *curl);
* performed transfer, all results from this function are undefined until the
* transfer is completed.
*/
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
/*
@ -59,7 +59,7 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
* 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);
CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
/*
* NAME curl_easy_reset()
@ -72,7 +72,7 @@ CURL* curl_easy_duphandle(CURL *curl);
* It does keep: live connections, the Session ID cache, the DNS cache and the
* cookies.
*/
void curl_easy_reset(CURL *curl);
CURL_EXTERN void curl_easy_reset(CURL *curl);
#ifdef __cplusplus
}

View File

@ -1,16 +1,18 @@
#ifndef __CURL_MPRINTF_H
#define __CURL_MPRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -21,34 +23,48 @@
* $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);
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
CURL_EXTERN int curl_mprintf(const char *format, ...);
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...);
CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, va_list args);
CURL_EXTERN char *curl_maprintf(const char *format, ...);
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
#ifdef _MPRINTF_REPLACE
# define printf curl_mprintf
# define fprintf curl_mfprintf
#ifdef CURLDEBUG
/* When built with CURLDEBUG we define away the sprintf() functions since we
don't want internal code to be using them */
# define sprintf sprintf_was_used
# define vsprintf vsprintf_was_used
#else
# define sprintf curl_msprintf
# define vsprintf curl_mvsprintf
#endif
# 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 */
#ifdef __cplusplus
}
#endif
#endif /* __CURL_MPRINTF_H */

View File

@ -1,18 +1,18 @@
#ifndef __CURL_MULTI_H
#define __CURL_MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -23,16 +23,8 @@
* $Id$
***************************************************************************/
/*
This is meant to be the "external" header file. Don't give away any
internals here!
This is an "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
@ -43,30 +35,18 @@
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
/*
* This header file should not really need to include "curl.h" since curl.h
* itself includes this file and we expect user applications to do #include
* <curl/curl.h> without the need for especially including multi.h.
*
* For some reason we added this include here at one point, and rather than to
* break existing (wrongly written) libcurl applications, we leave it as-is
* but with this warning attached.
*/
#include "curl.h"
#ifdef __cplusplus
@ -76,15 +56,23 @@ extern "C" {
typedef void CURLM;
typedef enum {
CURLM_CALL_MULTI_PERFORM=-1, /* please call curl_multi_perform() soon */
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
curl_multi_socket*() 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_BAD_SOCKET, /* the passed in socket argument did not match */
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_LAST
} CURLMcode;
/* just to make code nicer when using curl_multi_socket() you can now check
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
typedef enum {
CURLMSG_NONE, /* first, not used */
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
@ -106,27 +94,30 @@ 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);
CURL_EXTERN 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);
CURL_EXTERN 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);
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_fdset()
@ -134,13 +125,14 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
* 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);
CURL_EXTERN 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()
@ -158,8 +150,8 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
* still have occurred problems on invidual transfers even when this
* returns OK.
*/
CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
/*
* Name: curl_multi_cleanup()
@ -168,9 +160,10 @@ CURLMcode curl_multi_perform(CURLM *multi_handle,
* 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);
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
/*
* Name: curl_multi_info_read()
@ -200,22 +193,135 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle);
* queue (after this read) in the integer the second argument points
* to.
*/
CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue);
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue);
/*
* NAME curl_multi_strerror()
* Name: curl_multi_strerror()
*
* DESCRIPTION
* Desc: 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.
*
* 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.
* Returns: A pointer to a zero-terminated error message.
*/
const char *curl_multi_strerror(CURLMcode);
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
/*
* Name: curl_multi_socket() and
* curl_multi_socket_all()
*
* Desc: An alternative version of curl_multi_perform() that allows the
* application to pass in one of the file descriptors that have been
* detected to have "action" on them and let libcurl perform.
* See man page for details.
*/
#define CURL_POLL_NONE 0
#define CURL_POLL_IN 1
#define CURL_POLL_OUT 2
#define CURL_POLL_INOUT 3
#define CURL_POLL_REMOVE 4
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
void *userp, /* private callback
pointer */
void *socketp); /* private socket
pointer */
/*
* Name: curl_multi_timer_callback
*
* Desc: Called by libcurl whenever the library detects a change in the
* maximum number of milliseconds the app is allowed to wait before
* curl_multi_socket() or curl_multi_perform() must be called
* (to allow libcurl's timed events to take place).
*
* Returns: The callback should return zero.
*/
typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
long timeout_ms, /* see above */
void *userp); /* private callback
pointer */
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
int *running_handles);
/*
* Name: curl_multi_timeout()
*
* Desc: Returns the maximum number of milliseconds the app is allowed to
* wait before curl_multi_socket() or curl_multi_perform() must be
* called (to allow libcurl's timed events to take place).
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
long *milliseconds);
#undef CINIT /* re-using the same name as in curl.h */
#ifdef CURL_ISOCPP
#define CINIT(name,type,number) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + number
#else
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
#define LONG CURLOPTTYPE_LONG
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
#define OFF_T CURLOPTTYPE_OFF_T
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
#endif
typedef enum {
/* This is the socket callback function pointer */
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
/* This is the argument passed to the socket callback */
CINIT(SOCKETDATA, OBJECTPOINT, 2),
/* set to 1 to enable pipelining for this multi handle */
CINIT(PIPELINING, LONG, 3),
/* This is the timer callback function pointer */
CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
/* This is the argument passed to the timer callback */
CINIT(TIMERDATA, OBJECTPOINT, 5),
CURLMOPT_LASTENTRY /* the last unused */
} CURLMoption;
/*
* Name: curl_multi_setopt()
*
* Desc: Sets options for the multi handle.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURLMoption option, ...);
/*
* Name: curl_multi_assign()
*
* Desc: This function sets an association in the multi handle between the
* given socket and a private pointer of the application. This is
* (only) useful for curl_multi_socket uses.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
curl_socket_t sockfd, void *sockp);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -79,7 +79,19 @@
#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. */
easier to understand/patch. Undefine them first in case _MPRINTF_REPLACE
is set. */
# undef printf
# undef fprintf
# undef sprintf
# undef snprintf
# undef vprintf
# undef vfprintf
# undef vsprintf
# undef vsnprintf
# undef aprintf
# undef vaprintf
# define printf curlx_mprintf
# define fprintf curlx_mfprintf
# define sprintf curlx_msprintf

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -23,18 +23,22 @@
#include "setup.h"
#ifndef CURL_DISABLE_DICT
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef WIN32
#include <time.h>
#include <io.h>
#else
@ -42,7 +46,9 @@
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -79,20 +85,59 @@
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
CURLcode Curl_dict(struct connectdata *conn)
/* The last #include file should be: */
#include "memdebug.h"
static char *unescape_word(struct SessionHandle *data, char *inp)
{
char *newp;
char *dictp;
char *ptr;
int len;
unsigned char byte;
int olen=0;
newp = curl_easy_unescape(data, inp, 0, &len);
if(!newp)
return NULL;
dictp = malloc(len*2 + 1); /* add one for terminating zero */
if(dictp) {
/* According to RFC2229 section 2.2, these letters need to be escaped with
\[letter] */
for(ptr = newp;
(byte = (unsigned char)*ptr) != 0;
ptr++) {
if ((byte <= 32) || (byte == 127) ||
(byte == '\'') || (byte == '\"') || (byte == '\\')) {
dictp[olen++] = '\\';
}
dictp[olen++] = byte;
}
dictp[olen]=0;
free(newp);
}
return dictp;
}
CURLcode Curl_dict(struct connectdata *conn, bool *done)
{
char *word;
char *eword;
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;
CURLcode result=CURLE_OK;
struct SessionHandle *data=conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = conn->path;
curl_off_t *bytecount = &conn->bytecount;
char *path = data->reqdata.path;
curl_off_t *bytecount = &data->reqdata.keep.bytecount;
*done = TRUE; /* unconditionally */
if(conn->bits.user_passwd) {
/* AUTH is missing */
@ -101,7 +146,7 @@ CURLcode Curl_dict(struct connectdata *conn)
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++;
@ -118,7 +163,7 @@ CURLcode Curl_dict(struct connectdata *conn)
}
}
}
if ((word == NULL) || (*word == (char)0)) {
failf(data, "lookup word is missing");
}
@ -128,31 +173,38 @@ CURLcode Curl_dict(struct connectdata *conn)
if ((strategy == NULL) || (*strategy == (char)0)) {
strategy = (char *)".";
}
eword = unescape_word(data, word);
if(!eword)
return CURLE_OUT_OF_MEMORY;
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
"MATCH "
"%s " /* database */
"%s " /* strategy */
"%s\n" /* word */
"QUIT\n",
"%s\r\n" /* word */
"QUIT\r\n",
database,
strategy,
word
eword
);
free(eword);
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
result = Curl_setup_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++;
@ -165,57 +217,64 @@ CURLcode Curl_dict(struct connectdata *conn)
}
}
}
if ((word == NULL) || (*word == (char)0)) {
failf(data, "lookup word is missing");
}
if ((database == NULL) || (*database == (char)0)) {
database = (char *)"!";
}
eword = unescape_word(data, word);
if(!eword)
return CURLE_OUT_OF_MEMORY;
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
"DEFINE "
"%s " /* database */
"%s\n" /* word */
"QUIT\n",
"%s\r\n" /* word */
"QUIT\r\n",
database,
word);
eword);
free(eword);
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
result = Curl_setup_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);
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
"%s\r\n"
"QUIT\r\n", ppath);
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL);
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL);
if(result)
return result;
}
}
(void)nthdef;
return CURLE_OK;
}
#endif /*CURL_DISABLE_DICT*/

View File

@ -2,18 +2,18 @@
#define __DICT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -24,7 +24,7 @@
* $Id$
***************************************************************************/
#ifndef CURL_DISABLE_DICT
CURLcode Curl_dict(struct connectdata *conn);
CURLcode Curl_dict(struct connectdata *conn, bool *done);
CURLcode Curl_dict_done(struct connectdata *conn);
#endif
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -29,14 +29,18 @@
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include <errno.h>
#include "strequal.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef WIN32
#include <time.h>
#include <io.h>
#else
@ -44,7 +48,9 @@
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -71,20 +77,37 @@
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
#include "ssluse.h"
#include "sslgen.h"
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
#include "share.h"
#include "curl_memory.h"
#include "strdup.h"
#include "memory.h"
#include "progress.h"
#include "easyif.h"
#include "sendf.h" /* for failf function prototype */
#include <ca-bundle.h>
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
#include <iconv.h>
/* set default codesets for iconv */
#ifndef CURL_ICONV_CODESET_OF_NETWORK
#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
#endif
#ifndef CURL_ICONV_CODESET_FOR_UTF8
#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
#endif
#define ICONV_ERROR (size_t)-1
#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
/* The last #include file should be: */
#include "memdebug.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef USE_WINSOCK
/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
of win32_init() */
static void win32_cleanup(void)
@ -100,12 +123,12 @@ static CURLcode win32_init(void)
WSADATA wsaData;
int err;
#ifdef ENABLE_IPV6
wVersionRequested = MAKEWORD(2, 0);
#else
wVersionRequested = MAKEWORD(1, 1);
#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
Error IPV6_requires_winsock2
#endif
wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
@ -160,17 +183,31 @@ static void idna_init (void)
#endif /* USE_LIBIDN */
/* true globals -- for curl_global_init() and curl_global_cleanup() */
static unsigned int initialized = 0;
static long init_flags = 0;
static unsigned int initialized;
static long init_flags;
/*
* strdup (and other memory functions) is redefined in complicated
* ways, but at this point it must be defined as the system-supplied strdup
* so the callback pointer is initialized correctly.
*/
#if defined(_WIN32_WCE)
#define system_strdup _strdup
#elif !defined(HAVE_STRDUP)
#define system_strdup curlx_strdup
#else
#define system_strdup strdup
#endif
/*
* 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_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
/**
@ -179,18 +216,19 @@ curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
*/
CURLcode curl_global_init(long flags)
{
if (initialized)
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_cstrdup = (curl_strdup_callback)system_strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
if (flags & CURL_GLOBAL_SSL)
Curl_SSL_init();
if (!Curl_ssl_init())
return CURLE_FAILED_INIT;
if (flags & CURL_GLOBAL_WIN32)
if (win32_init() != CURLE_OK)
@ -205,7 +243,6 @@ CURLcode curl_global_init(long flags)
idna_init();
#endif
initialized = 1;
init_flags = flags;
return CURLE_OK;
@ -219,7 +256,7 @@ 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;
CURLcode code = CURLE_OK;
/* Invalid input, return immediately */
if (!m || !f || !r || !s || !c)
@ -251,10 +288,13 @@ void curl_global_cleanup(void)
if (!initialized)
return;
if (--initialized)
return;
Curl_global_host_cache_dtor();
if (init_flags & CURL_GLOBAL_SSL)
Curl_SSL_cleanup();
Curl_ssl_cleanup();
if (init_flags & CURL_GLOBAL_WIN32)
win32_cleanup();
@ -263,7 +303,6 @@ void curl_global_cleanup(void)
amiga_cleanup();
#endif
initialized = 0;
init_flags = 0;
}
@ -296,14 +335,10 @@ CURL *curl_easy_init(void)
* 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;
@ -312,38 +347,95 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
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);
}
ret = Curl_setopt(data, tag, arg);
va_end(arg);
return ret;
}
#ifdef CURL_MULTIEASY
/***************************************************************************
* This function is still only for testing purposes. It makes a great way
* to run the full test suite on the multi interface instead of the easy one.
***************************************************************************
*
* The *new* curl_easy_perform() is the external interface that performs a
* transfer previously setup.
*
* Wrapper-function that: creates a multi handle, adds the easy handle to it,
* runs curl_multi_perform() until the transfer is done, then detaches the
* easy handle, destroys the multi handle and returns the easy handle's return
* code. This will make everything internally use and assume multi interface.
*/
CURLcode curl_easy_perform(CURL *easy)
{
CURLM *multi;
CURLMcode mcode;
CURLcode code = CURLE_OK;
int still_running;
struct timeval timeout;
int rc;
CURLMsg *msg;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
if(!easy)
return CURLE_BAD_FUNCTION_ARGUMENT;
multi = curl_multi_init();
if(!multi)
return CURLE_OUT_OF_MEMORY;
mcode = curl_multi_add_handle(multi, easy);
if(mcode) {
curl_multi_cleanup(multi);
return CURLE_FAILED_INIT;
}
/* we start some action by calling perform right away */
do {
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi, &still_running));
if(!still_running)
break;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* timeout once per second */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
if(rc == -1)
/* select error */
break;
/* timeout or data to send/receive => loop! */
} while(still_running);
msg = curl_multi_info_read(multi, &rc);
if(msg)
code = msg->data.result;
mcode = curl_multi_remove_handle(multi, easy);
/* what to do if it fails? */
mcode = curl_multi_cleanup(multi);
/* what to do if it fails? */
return code;
}
#else
/*
* curl_easy_perform() is the external interface that performs a transfer
* previously setup.
@ -358,16 +450,18 @@ CURLcode curl_easy_perform(CURL *curl)
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();
(data->dns.hostcachetype != HCACHE_GLOBAL)) {
if (data->dns.hostcachetype == HCACHE_PRIVATE)
Curl_hash_destroy(data->dns.hostcache);
data->dns.hostcache = Curl_global_host_cache_get();
data->dns.hostcachetype = HCACHE_GLOBAL;
}
if (!data->hostcache) {
data->hostcache = Curl_mk_dnscache();
if (!data->dns.hostcache) {
data->dns.hostcachetype = HCACHE_PRIVATE;
data->dns.hostcache = Curl_mk_dnscache();
if(!data->hostcache)
if(!data->dns.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! */
@ -376,8 +470,16 @@ CURLcode curl_easy_perform(CURL *curl)
}
if(!data->state.connc) {
/* oops, no connection cache, make one up */
data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
if(!data->state.connc)
return CURLE_OUT_OF_MEMORY;
}
return Curl_perform(data);
}
#endif
/*
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
@ -390,14 +492,25 @@ void curl_easy_cleanup(CURL *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);
}
/*
* Store a pointed to the multi handle within the easy handle's data struct.
*/
void Curl_easy_addmulti(struct SessionHandle *data,
void *multi)
{
data->multi = multi;
}
void Curl_easy_initHandleData(struct SessionHandle *data)
{
memset(&data->reqdata, 0, sizeof(struct HandleData));
data->reqdata.maxdownload = -1;
}
/*
* curl_easy_getinfo() is an external interface that allows an app to retrieve
* information from a performed transfer and similar.
@ -445,21 +558,21 @@ CURL *curl_easy_duphandle(CURL *incurl)
/* 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) {
if(data->state.used_interface == Curl_if_multi)
outcurl->state.connc = data->state.connc;
else
outcurl->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
if(!outcurl->state.connc)
break;
}
memset(outcurl->state.connects, 0,
sizeof(struct connectdata *)*outcurl->state.numconnects);
outcurl->state.lastconnect = -1;
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
#ifndef CURL_DISABLE_HTTP
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(data->cookies) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
@ -474,18 +587,14 @@ CURL *curl_easy_duphandle(CURL *incurl)
#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)
@ -499,18 +608,29 @@ CURL *curl_easy_duphandle(CURL *incurl)
break;
#endif
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
outcurl->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_OF_NETWORK);
outcurl->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
CURL_ICONV_CODESET_OF_HOST);
outcurl->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_FOR_UTF8);
#endif
Curl_easy_initHandleData(outcurl);
outcurl->magic = CURLEASY_MAGIC_NUMBER;
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.connc->type == CONNCACHE_PRIVATE)
Curl_rm_connc(outcurl->state.connc);
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)
@ -531,12 +651,21 @@ void curl_easy_reset(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
Curl_safefree(data->reqdata.pathbuffer);
data->reqdata.pathbuffer=NULL;
Curl_safefree(data->reqdata.proto.generic);
data->reqdata.proto.generic=NULL;
/* zero out UserDefined data: */
memset(&data->set, 0, sizeof(struct UserDefined));
/* zero out Progress data: */
memset(&data->progress, 0, sizeof(struct Progress));
/* init Handle data */
Curl_easy_initHandleData(data);
/* The remainder of these calls have been taken from Curl_open() */
data->set.out = stdout; /* default output to stdout */
@ -550,6 +679,7 @@ void curl_easy_reset(CURL *curl)
data->set.fread = (curl_read_callback)fread;
data->set.infilesize = -1; /* we don't know any size */
data->set.postfieldsize = -1;
data->state.current_speed = -1; /* init to negative == impossible */
@ -561,6 +691,7 @@ void curl_easy_reset(CURL *curl)
/* make libcurl quiet by default: */
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
data->progress.flags |= PGRS_HIDE;
/* Set the default size of the SSL session ID cache */
data->set.ssl.numsessions = 5;
@ -580,4 +711,185 @@ void curl_easy_reset(CURL *curl)
/* This is our prefered CA cert bundle since install time */
data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
#endif
data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
type */
}
#ifdef CURL_DOES_CONVERSIONS
/*
* Curl_convert_to_network() is an internal function
* for performing ASCII conversions on non-ASCII platforms.
*/
CURLcode Curl_convert_to_network(struct SessionHandle *data,
char *buffer, size_t length)
{
CURLcode rc;
if(data->set.convtonetwork) {
/* use translation callback */
rc = data->set.convtonetwork(buffer, length);
if(rc != CURLE_OK) {
failf(data,
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %i: %s",
rc, curl_easy_strerror(rc));
}
return(rc);
} else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
char *input_ptr, *output_ptr;
size_t in_bytes, out_bytes, rc;
/* open an iconv conversion descriptor if necessary */
if(data->outbound_cd == (iconv_t)-1) {
data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
CURL_ICONV_CODESET_OF_HOST);
if(data->outbound_cd == (iconv_t)-1) {
failf(data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_NETWORK,
CURL_ICONV_CODESET_OF_HOST,
errno, strerror(errno));
return CURLE_CONV_FAILED;
}
}
/* call iconv */
input_ptr = output_ptr = buffer;
in_bytes = out_bytes = length;
rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
&output_ptr, &out_bytes);
if ((rc == ICONV_ERROR) || (in_bytes != 0)) {
failf(data,
"The Curl_convert_to_network iconv call failed with errno %i: %s",
errno, strerror(errno));
return CURLE_CONV_FAILED;
}
#else
failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
return CURLE_CONV_REQD;
#endif /* HAVE_ICONV */
}
return CURLE_OK;
}
/*
* Curl_convert_from_network() is an internal function
* for performing ASCII conversions on non-ASCII platforms.
*/
CURLcode Curl_convert_from_network(struct SessionHandle *data,
char *buffer, size_t length)
{
CURLcode rc;
if(data->set.convfromnetwork) {
/* use translation callback */
rc = data->set.convfromnetwork(buffer, length);
if(rc != CURLE_OK) {
failf(data,
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %i: %s",
rc, curl_easy_strerror(rc));
}
return(rc);
} else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
char *input_ptr, *output_ptr;
size_t in_bytes, out_bytes, rc;
/* open an iconv conversion descriptor if necessary */
if(data->inbound_cd == (iconv_t)-1) {
data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_OF_NETWORK);
if(data->inbound_cd == (iconv_t)-1) {
failf(data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_OF_NETWORK,
errno, strerror(errno));
return CURLE_CONV_FAILED;
}
}
/* call iconv */
input_ptr = output_ptr = buffer;
in_bytes = out_bytes = length;
rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
&output_ptr, &out_bytes);
if ((rc == ICONV_ERROR) || (in_bytes != 0)) {
failf(data,
"The Curl_convert_from_network iconv call failed with errno %i: %s",
errno, strerror(errno));
return CURLE_CONV_FAILED;
}
#else
failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
return CURLE_CONV_REQD;
#endif /* HAVE_ICONV */
}
return CURLE_OK;
}
/*
* Curl_convert_from_utf8() is an internal function
* for performing UTF-8 conversions on non-ASCII platforms.
*/
CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
char *buffer, size_t length)
{
CURLcode rc;
if(data->set.convfromutf8) {
/* use translation callback */
rc = data->set.convfromutf8(buffer, length);
if(rc != CURLE_OK) {
failf(data,
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %i: %s",
rc, curl_easy_strerror(rc));
}
return(rc);
} else {
#ifdef HAVE_ICONV
/* do the translation ourselves */
char *input_ptr, *output_ptr;
size_t in_bytes, out_bytes, rc;
/* open an iconv conversion descriptor if necessary */
if(data->utf8_cd == (iconv_t)-1) {
data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_FOR_UTF8);
if(data->utf8_cd == (iconv_t)-1) {
failf(data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_FOR_UTF8,
errno, strerror(errno));
return CURLE_CONV_FAILED;
}
}
/* call iconv */
input_ptr = output_ptr = buffer;
in_bytes = out_bytes = length;
rc = iconv(data->utf8_cd, (const char**)&input_ptr, &in_bytes,
&output_ptr, &out_bytes);
if ((rc == ICONV_ERROR) || (in_bytes != 0)) {
failf(data,
"The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
errno, strerror(errno));
return CURLE_CONV_FAILED;
}
if (output_ptr < input_ptr) {
/* null terminate the now shorter output string */
*output_ptr = 0x00;
}
#else
failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
return CURLE_CONV_REQD;
#endif /* HAVE_ICONV */
}
return CURLE_OK;
}
#endif /* CURL_DOES_CONVERSIONS */

40
Utilities/cmcurl/easyif.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __EASYIF_H
#define __EASYIF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, 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$
***************************************************************************/
/*
* Prototypes for library-wide functions provided by easy.c
*/
void Curl_easy_addmulti(struct SessionHandle *data, void *multi);
void Curl_easy_initHandleData(struct SessionHandle *data);
CURLcode Curl_convert_to_network(struct SessionHandle *data,
char *buffer, size_t length);
CURLcode Curl_convert_from_network(struct SessionHandle *data,
char *buffer, size_t length);
CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
char *buffer, size_t length);
#endif /* __EASYIF_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -31,7 +31,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl_memory.h"
#include "memory.h"
/* urldata.h and easyif.h are included for Curl_convert_... prototypes */
#include "urldata.h"
#include "easyif.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -39,16 +42,32 @@
/* The last #include file should be: */
#include "memdebug.h"
/* for ABI-compatibility with previous versions */
char *curl_escape(const char *string, int inlength)
{
return curl_easy_escape(NULL, string, inlength);
}
/* for ABI-compatibility with previous versions */
char *curl_unescape(const char *string, int length)
{
return curl_easy_unescape(NULL, string, length, NULL);
}
char *curl_easy_escape(CURL *handle, const char *string, int inlength)
{
size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
char *ns;
char *testing_ptr;
char *testing_ptr = NULL;
unsigned char in;
size_t newlen = alloc;
int strindex=0;
size_t length;
#ifndef CURL_DOES_CONVERSIONS
/* avoid compiler warnings */
(void)handle;
#endif
ns = malloc(alloc);
if(!ns)
return NULL;
@ -72,6 +91,17 @@ char *curl_escape(const char *string, int inlength)
ns = testing_ptr;
}
}
#ifdef CURL_DOES_CONVERSIONS
/* escape sequences are always in ASCII so convert them on non-ASCII hosts */
if (!handle ||
(Curl_convert_to_network(handle, &in, 1) != CURLE_OK)) {
/* Curl_convert_to_network calls failf if unsuccessful */
free(ns);
return NULL;
}
#endif /* CURL_DOES_CONVERSIONS */
snprintf(&ns[strindex], 4, "%%%02X", in);
strindex+=3;
@ -86,11 +116,8 @@ char *curl_escape(const char *string, int inlength)
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)
char *curl_easy_unescape(CURL *handle, const char *string, int length,
int *olen)
{
int alloc = (length?length:(int)strlen(string))+1;
char *ns = malloc(alloc);
@ -98,12 +125,16 @@ char *curl_unescape(const char *string, int length)
int strindex=0;
long hex;
#ifndef CURL_DOES_CONVERSIONS
/* avoid compiler warnings */
(void)handle;
#endif
if( !ns )
return NULL;
while(--alloc > 0) {
in = *string;
if(('%' == in) && ishex(string[1]) && ishex(string[2])) {
if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
char hexstr[3];
char *ptr;
@ -114,6 +145,17 @@ char *curl_unescape(const char *string, int length)
hex = strtol(hexstr, &ptr, 16);
in = (unsigned char)hex; /* this long is never bigger than 255 anyway */
#ifdef CURL_DOES_CONVERSIONS
/* escape sequences are always in ASCII so convert them on non-ASCII hosts */
if (!handle ||
(Curl_convert_from_network(handle, &in, 1) != CURLE_OK)) {
/* Curl_convert_from_network calls failf if unsuccessful */
free(ns);
return NULL;
}
#endif /* CURL_DOES_CONVERSIONS */
string+=2;
alloc-=2;
}
@ -122,6 +164,10 @@ char *curl_unescape(const char *string, int length)
string++;
}
ns[strindex]=0; /* terminate it */
if(olen)
/* store output size */
*olen = strindex;
return ns;
}

View File

@ -2,18 +2,18 @@
#define __ESCAPE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -26,7 +26,5 @@
/* 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

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -30,12 +30,14 @@
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef WIN32
#include <time.h>
#include <io.h>
#include <fcntl.h>
@ -46,7 +48,9 @@
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -66,9 +70,6 @@
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@ -85,7 +86,8 @@
#include "getinfo.h"
#include "transfer.h"
#include "url.h"
#include "curl_memory.h"
#include "memory.h"
#include "parsedate.h" /* for the week day and month names */
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -100,10 +102,10 @@
*/
CURLcode Curl_file_connect(struct connectdata *conn)
{
char *real_path = curl_unescape(conn->path, 0);
char *real_path = curl_easy_unescape(conn->data, conn->data->reqdata.path, 0, NULL);
struct FILEPROTO *file;
int fd;
#if defined(WIN32) || defined(__EMX__)
#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
int i;
char *actual_path;
#endif
@ -117,9 +119,13 @@ CURLcode Curl_file_connect(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
}
conn->proto.file = file;
if (conn->data->reqdata.proto.file) {
free(conn->data->reqdata.proto.file);
}
#if defined(WIN32) || defined(__EMX__)
conn->data->reqdata.proto.file = file;
#if defined(WIN32) || defined(MSDOS) || 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
@ -143,7 +149,7 @@ CURLcode Curl_file_connect(struct connectdata *conn)
actual_path++;
}
/* change path separators from '/' to '\\' for Windows and OS/2 */
/* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
for (i=0; actual_path[i] != '\0'; ++i)
if (actual_path[i] == '/')
actual_path[i] = '\\';
@ -156,31 +162,31 @@ CURLcode Curl_file_connect(struct connectdata *conn)
#endif
file->freepath = real_path; /* free this when done */
file->fd = fd;
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);
failf(conn->data, "Couldn't open file %s", conn->data->reqdata.path);
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE);
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)
CURLcode status, bool premature)
{
struct FILEPROTO *file = conn->proto.file;
struct FILEPROTO *file = conn->data->reqdata.proto.file;
(void)status; /* not used */
(void)premature; /* not used */
Curl_safefree(file->freepath);
if(file->fd != -1)
close(file->fd);
return CURLE_OK;
}
#if defined(WIN32) || defined(__EMX__)
#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
#define DIRSEP '\\'
#else
#define DIRSEP '/'
@ -188,7 +194,7 @@ CURLcode Curl_file_done(struct connectdata *conn,
static CURLcode file_upload(struct connectdata *conn)
{
struct FILEPROTO *file = conn->proto.file;
struct FILEPROTO *file = conn->data->reqdata.proto.file;
char *dir = strchr(file->path, DIRSEP);
FILE *fp;
CURLcode res=CURLE_OK;
@ -205,7 +211,7 @@ static CURLcode file_upload(struct connectdata *conn)
*/
conn->fread = data->set.fread;
conn->fread_in = data->set.in;
conn->upload_fromhere = buf;
conn->data->reqdata.upload_fromhere = buf;
if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
@ -227,13 +233,13 @@ static CURLcode file_upload(struct connectdata *conn)
int readcount;
res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
if(res)
return res;
break;
if (readcount <= 0) /* fix questionable compare error. curlvms */
break;
nread = (size_t)readcount;
if (nread <= 0)
break;
/* write the data to the target */
nwrite = fwrite(buf, 1, nread, fp);
if(nwrite != nread) {
@ -266,7 +272,7 @@ static CURLcode file_upload(struct connectdata *conn)
* opposed to sockets) we instead perform the whole do-operation in this
* function.
*/
CURLcode Curl_file(struct connectdata *conn)
CURLcode Curl_file(struct connectdata *conn, bool *done)
{
/* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system)
@ -274,7 +280,9 @@ CURLcode Curl_file(struct connectdata *conn)
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
CURLcode res = CURLE_OK;
struct stat statbuf;
struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
Windows version to have a different struct without
having to redefine the simple word 'stat' */
curl_off_t expected_size=0;
bool fstated=FALSE;
ssize_t nread;
@ -284,6 +292,8 @@ CURLcode Curl_file(struct connectdata *conn)
int fd;
struct timeval now = Curl_tvnow();
*done = TRUE; /* unconditionally */
Curl_readwrite_init(conn);
Curl_initinfo(data);
Curl_pgrsStartNow(data);
@ -292,7 +302,7 @@ CURLcode Curl_file(struct connectdata *conn)
return file_upload(conn);
/* get the fd from the connection phase */
fd = conn->proto.file->fd;
fd = conn->data->reqdata.proto.file->fd;
/* VMS: This only works reliable for STREAMLF files */
if( -1 != fstat(fd, &statbuf)) {
@ -308,40 +318,45 @@ CURLcode Curl_file(struct connectdata *conn)
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);
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
if(result)
return result;
result = Curl_client_write(data, CLIENTWRITE_BOTH,
result = Curl_client_write(conn, 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;
time_t clock = (time_t)statbuf.st_mtime;
#ifdef HAVE_GMTIME_R
struct tm buffer;
tm = (struct tm *)gmtime_r(&cuClock, &buffer);
tm = (struct tm *)gmtime_r(&clock, &buffer);
#else
tm = gmtime(&cuClock);
tm = gmtime(&clock);
#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);
snprintf(buf, BUFSIZE-1,
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
Curl_month[tm->tm_mon],
tm->tm_year + 1900,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
result = Curl_client_write(conn, 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 (data->reqdata.resume_from <= expected_size)
expected_size -= data->reqdata.resume_from;
else {
failf(data, "failed to resume file:// transfer");
return CURLE_BAD_DOWNLOAD_RESUME;
}
if (fstated && (expected_size == 0))
return CURLE_OK;
@ -353,8 +368,11 @@ CURLcode Curl_file(struct connectdata *conn)
if(fstated)
Curl_pgrsSetDownloadSize(data, expected_size);
if(conn->resume_from)
lseek(fd, conn->resume_from, SEEK_SET);
if(data->reqdata.resume_from) {
if(data->reqdata.resume_from !=
lseek(fd, data->reqdata.resume_from, SEEK_SET))
return CURLE_BAD_DOWNLOAD_RESUME;
}
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
@ -369,7 +387,7 @@ CURLcode Curl_file(struct connectdata *conn)
bytecount += nread;
res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
if(res)
return res;
@ -383,8 +401,7 @@ CURLcode Curl_file(struct connectdata *conn)
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
close(fd);
return res;
}
#endif

View File

@ -2,18 +2,18 @@
#define __FILE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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.
@ -24,8 +24,8 @@
* $Id$
***************************************************************************/
#ifndef CURL_DISABLE_FILE
CURLcode Curl_file(struct connectdata *);
CURLcode Curl_file_done(struct connectdata *, CURLcode);
CURLcode Curl_file(struct connectdata *, bool *done);
CURLcode Curl_file_done(struct connectdata *, CURLcode, bool premature);
CURLcode Curl_file_connect(struct connectdata *);
#endif
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -24,7 +24,7 @@
/*
Debug the form generator stand-alone by compiling this source file with:
gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -o formdata -I../include formdata.c strequal.c
gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -DCURLDEBUG -o formdata -I../include formdata.c strequal.c memdebug.c mprintf.c strerror.c
run the 'formdata' executable the output should end with:
All Tests seem to have worked ...
@ -63,7 +63,7 @@ Content-Type: multipart/mixed, boundary=curlz1s0dkticx49MV1KGcYP5cvfSsz
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="Makefile.b32.resp"
Content-Disposition: attachment; filename="Makefile.b32"
Content-Type: text/plain
...
@ -73,7 +73,7 @@ Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="Makefile.b32.resp"
Content-Disposition: attachment; filename="Makefile.b32"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
@ -87,7 +87,7 @@ Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1
Content-Disposition: attachment; filename="inet_ntoa_r.h"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="Makefile.b32.resp"
Content-Disposition: attachment; filename="Makefile.b32"
Content-Type: text/plain
...
Content-Disposition: attachment; filename="inet_ntoa_r.h"
@ -105,17 +105,24 @@ Content-Disposition: form-data; name="FILECONTENT"
/* Length of the random boundary string. */
#define BOUNDARY_LENGTH 40
#ifndef CURL_DISABLE_HTTP
#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
#endif
#include "urldata.h" /* for struct SessionHandle */
#include "easyif.h" /* for Curl_convert_... prototypes */
#include "formdata.h"
#include "strequal.h"
#include "curl_memory.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -123,6 +130,17 @@ Content-Disposition: form-data; name="FILECONTENT"
/* The last #include file should be: */
#include "memdebug.h"
#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */
#ifndef CURL_DISABLE_HTTP
#if defined(HAVE_BASENAME) && defined(NEED_BASENAME_PROTO)
/* This system has a basename() but no prototype for it! */
char *basename(char *path);
#endif
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
/* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
@ -241,7 +259,7 @@ static FormInfo * AddFormInfo(char *value,
static const char * ContentTypeForFilename (const char *filename,
const char *prevtype)
{
const char *contenttype;
const char *contenttype = NULL;
unsigned int i;
/*
* No type was specified, we scan through a few well-known
@ -251,7 +269,7 @@ static const char * ContentTypeForFilename (const char *filename,
const char *extension;
const char *type;
};
static struct ContentType ctts[]={
static const struct ContentType ctts[]={
{".gif", "image/gif"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
@ -374,7 +392,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
FormInfo *first_form, *current_form, *form = NULL;
CURLFORMcode return_value = CURL_FORMADD_OK;
const char *prevtype = NULL;
struct curl_httppost *post;
struct curl_httppost *post = NULL;
CURLformoption option;
struct curl_forms *forms = NULL;
char *array_value=NULL; /* value read from an array */
@ -436,7 +454,12 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
* Set the Name property.
*/
case CURLFORM_PTRNAME:
#ifdef CURL_DOES_CONVERSIONS
/* treat CURLFORM_PTR like CURLFORM_COPYNAME so we'll
have safe memory for the eventual conversion */
#else
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
#endif
case CURLFORM_COPYNAME:
if (current_form->name)
return_value = CURL_FORMADD_OPTION_TWICE;
@ -454,7 +477,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
return_value = CURL_FORMADD_OPTION_TWICE;
else
current_form->namelength =
array_state?(long)array_value:va_arg(params, long);
array_state?(long)array_value:(long)va_arg(params, long);
break;
/*
@ -512,8 +535,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
if (current_form->value) {
if (current_form->flags & HTTPPOST_FILENAME) {
if (filename) {
if (!(current_form = AddFormInfo(strdup(filename),
NULL, current_form)))
if ((current_form = AddFormInfo(strdup(filename),
NULL, current_form)) == NULL)
return_value = CURL_FORMADD_MEMORY;
}
else
@ -546,8 +569,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
if (current_form->value) {
if (current_form->flags & HTTPPOST_BUFFER) {
if (filename) {
if (!(current_form = AddFormInfo(strdup(filename),
NULL, current_form)))
if ((current_form = AddFormInfo(strdup(filename),
NULL, current_form)) == NULL)
return_value = CURL_FORMADD_MEMORY;
}
else
@ -598,9 +621,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
if (current_form->contenttype) {
if (current_form->flags & HTTPPOST_FILENAME) {
if (contenttype) {
if (!(current_form = AddFormInfo(NULL,
strdup(contenttype),
current_form)))
if ((current_form = AddFormInfo(NULL,
strdup(contenttype),
current_form)) == NULL)
return_value = CURL_FORMADD_MEMORY;
}
else
@ -626,15 +649,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
{
/* this "cast increases required alignment of target type" but
we consider it OK anyway */
struct curl_slist* list = 0;
if ( array_state )
{
memcpy(&list, &array_value, sizeof(struct curl_slist*));
}
else
{
list = va_arg(params, struct curl_slist*);
}
struct curl_slist* list = array_state?
(struct curl_slist*)array_value:
va_arg(params, struct curl_slist*);
if( current_form->contentheader )
return_value = CURL_FORMADD_OPTION_TWICE;
@ -825,13 +842,13 @@ static CURLcode AddFormData(struct FormData **formp,
*formp = newform;
if (size) {
if(type == FORM_DATA)
if((type == FORM_DATA) || (type == FORM_CONTENT))
*size += length;
else {
/* Since this is a file to be uploaded here, add the size of the actual
file */
if(!strequal("-", newform->line)) {
struct stat file;
struct_stat file;
if(!stat(newform->line, &file)) {
*size += file.st_size;
}
@ -862,10 +879,11 @@ static CURLcode AddFormDataf(struct FormData **formp,
* Curl_formclean() is used from http.c, this cleans a built FormData linked
* list
*/
void Curl_formclean(struct FormData *form)
void Curl_formclean(struct FormData **form_ptr)
{
struct FormData *next;
struct FormData *next, *form;
form = *form_ptr;
if(!form)
return;
@ -874,7 +892,84 @@ void Curl_formclean(struct FormData *form)
free(form->line); /* free the line */
free(form); /* free the struct */
} while((form=next)); /* continue */
} while ((form = next) != NULL); /* continue */
*form_ptr = NULL;
}
#ifdef CURL_DOES_CONVERSIONS
/*
* Curl_formcovert() is used from http.c, this converts any
form items that need to be sent in the network encoding.
Returns CURLE_OK on success.
*/
CURLcode Curl_formconvert(struct SessionHandle *data, struct FormData *form)
{
struct FormData *next;
CURLcode rc;
if(!form)
return CURLE_OK;
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
do {
next=form->next; /* the following form line */
if (form->type == FORM_DATA) {
rc = Curl_convert_to_network(data, form->line, form->length);
/* Curl_convert_to_network calls failf if unsuccessful */
if (rc != CURLE_OK)
return rc;
}
} while ((form = next) != NULL); /* continue */
return CURLE_OK;
}
#endif /* CURL_DOES_CONVERSIONS */
/*
* curl_formget()
* Serialize a curl_httppost struct.
* Returns 0 on success.
*/
int curl_formget(struct curl_httppost *form, void *arg,
curl_formget_callback append)
{
CURLcode rc;
curl_off_t size;
struct FormData *data, *ptr;
rc = Curl_getFormData(&data, form, NULL, &size);
if (rc != CURLE_OK)
return (int)rc;
for (ptr = data; ptr; ptr = ptr->next) {
if (ptr->type == FORM_FILE) {
char buffer[8192];
size_t read;
struct Form temp;
Curl_FormInit(&temp, ptr);
do {
read = readfromfile(&temp, buffer, sizeof(buffer));
if ((read == (size_t) -1) || (read != append(arg, buffer, read))) {
if (temp.fp) {
fclose(temp.fp);
}
Curl_formclean(&data);
return -1;
}
} while (read == sizeof(buffer));
} else {
if (ptr->length != append(arg, ptr->line, ptr->length)) {
Curl_formclean(&data);
return -1;
}
}
}
Curl_formclean(&data);
return 0;
}
/*
@ -906,7 +1001,69 @@ void curl_formfree(struct curl_httppost *form)
free(form->showfilename); /* free the faked file name */
free(form); /* free the struct */
} while((form=next)); /* continue */
} while ((form = next) != NULL); /* continue */
}
#ifndef HAVE_BASENAME
/*
(Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
Edition)
The basename() function shall take the pathname pointed to by path and
return a pointer to the final component of the pathname, deleting any
trailing '/' characters.
If the string pointed to by path consists entirely of the '/' character,
basename() shall return a pointer to the string "/". If the string pointed
to by path is exactly "//", it is implementation-defined whether '/' or "//"
is returned.
If path is a null pointer or points to an empty string, basename() shall
return a pointer to the string ".".
The basename() function may modify the string pointed to by path, and may
return a pointer to static storage that may then be overwritten by a
subsequent call to basename().
The basename() function need not be reentrant. A function that is not
required to be reentrant is not required to be thread-safe.
*/
static char *basename(char *path)
{
/* Ignore all the details above for now and make a quick and simple
implementaion here */
char *s1;
char *s2;
s1=strrchr(path, '/');
s2=strrchr(path, '\\');
if(s1 && s2) {
path = (s1 > s2? s1 : s2)+1;
}
else if(s1)
path = s1 + 1;
else if(s2)
path = s2 + 1;
return path;
}
#endif
static char *strippath(char *fullfile)
{
char *filename;
char *base;
filename = strdup(fullfile); /* duplicate since basename() may ruin the
buffer it works on */
if(!filename)
return NULL;
base = strdup(basename(filename));
free(filename); /* free temporary buffer */
return base; /* returns an allocated string! */
}
/*
@ -914,10 +1071,13 @@ void curl_formfree(struct curl_httppost *form)
* (possibly huge) multipart formdata. The input list is in 'post', while the
* output resulting linked lists gets stored in '*finalform'. *sizep will get
* the total size of the whole POST.
* A multipart/form_data content-type is built, unless a custom content-type
* is passed in 'custom_content_type'.
*/
CURLcode Curl_getFormData(struct FormData **finalform,
struct curl_httppost *post,
const char *custom_content_type,
curl_off_t *sizep)
{
struct FormData *form = NULL;
@ -941,9 +1101,11 @@ CURLcode Curl_getFormData(struct FormData **finalform,
/* Make the first line of the output */
result = AddFormDataf(&form, NULL,
"Content-Type: multipart/form-data;"
" boundary=%s\r\n",
"%s; boundary=%s\r\n",
custom_content_type?custom_content_type:
"Content-Type: multipart/form-data",
boundary);
if (result) {
free(boundary);
return result;
@ -966,6 +1128,10 @@ CURLcode Curl_getFormData(struct FormData **finalform,
if (result)
break;
/* Maybe later this should be disabled when a custom_content_type is
passed, since Content-Disposition is not meaningful for all multipart
types.
*/
result = AddFormDataf(&form, &size,
"Content-Disposition: form-data; name=\"");
if (result)
@ -1004,22 +1170,33 @@ CURLcode Curl_getFormData(struct FormData **finalform,
if(post->more) {
/* if multiple-file */
char *filebasename=
(!file->showfilename)?strippath(file->contents):NULL;
result = AddFormDataf(&form, &size,
"\r\n--%s\r\nContent-Disposition: "
"attachment; filename=\"%s\"",
fileboundary,
(file->showfilename?file->showfilename:
file->contents));
filebasename));
if (filebasename)
free(filebasename);
if (result)
break;
}
else if((post->flags & HTTPPOST_FILENAME) ||
(post->flags & HTTPPOST_BUFFER)) {
char *filebasename=
(!post->showfilename)?strippath(post->contents):NULL;
result = AddFormDataf(&form, &size,
"; filename=\"%s\"",
(post->showfilename?post->showfilename:
post->contents));
filebasename));
if (filebasename)
free(filebasename);
if (result)
break;
}
@ -1042,7 +1219,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
curList = curList->next;
}
if (result) {
Curl_formclean(firstform);
Curl_formclean(&firstform);
free(boundary);
return result;
}
@ -1057,7 +1234,10 @@ CURLcode Curl_getFormData(struct FormData **finalform,
if(file->contenttype &&
!checkprefix("text/", file->contenttype)) {
/* this is not a text content, mention our binary encoding */
size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
result = AddFormDataf(&form, &size,
"\r\nContent-Transfer-Encoding: binary");
if (result)
break;
}
#endif
@ -1094,22 +1274,27 @@ CURLcode Curl_getFormData(struct FormData **finalform,
*/
size_t nread;
char buffer[512];
while((nread = fread(buffer, 1, sizeof(buffer), fileread))) {
result = AddFormData(&form, FORM_DATA, buffer, nread, &size);
while ((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
if (result)
break;
}
}
if (result) {
Curl_formclean(firstform);
Curl_formclean(&firstform);
free(boundary);
return result;
}
}
else {
Curl_formclean(firstform);
#ifdef _FORM_DEBUG
fprintf(stderr,
"\n==> Curl_getFormData couldn't open/read \"%s\"\n",
file->contents);
#endif
Curl_formclean(&firstform);
free(boundary);
*finalform = NULL;
return CURLE_READ_ERROR;
@ -1118,7 +1303,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
}
else if (post->flags & HTTPPOST_BUFFER) {
/* include contents of buffer */
result = AddFormData(&form, FORM_DATA, post->buffer,
result = AddFormData(&form, FORM_CONTENT, post->buffer,
post->bufferlength, &size);
if (result)
break;
@ -1126,14 +1311,14 @@ CURLcode Curl_getFormData(struct FormData **finalform,
else {
/* include the contents we got */
result = AddFormData(&form, FORM_DATA, post->contents,
result = AddFormData(&form, FORM_CONTENT, post->contents,
post->contentslength, &size);
if (result)
break;
}
} while((file = file->more)); /* for each specified file for this field */
} while ((file = file->more) != NULL); /* for each specified file for this field */
if (result) {
Curl_formclean(firstform);
Curl_formclean(&firstform);
free(boundary);
return result;
}
@ -1149,9 +1334,9 @@ CURLcode Curl_getFormData(struct FormData **finalform,
break;
}
} while((post=post->next)); /* for each field */
} while ((post = post->next) != NULL); /* for each field */
if (result) {
Curl_formclean(firstform);
Curl_formclean(&firstform);
free(boundary);
return result;
}
@ -1161,7 +1346,7 @@ CURLcode Curl_getFormData(struct FormData **finalform,
"\r\n--%s--\r\n",
boundary);
if (result) {
Curl_formclean(firstform);
Curl_formclean(&firstform);
free(boundary);
return result;
}
@ -1198,12 +1383,12 @@ static size_t readfromfile(struct Form *form, char *buffer, size_t size)
/* this file hasn't yet been opened */
form->fp = fopen(form->data->line, "rb"); /* b is for binary */
if(!form->fp)
return -1; /* failure */
return (size_t)-1; /* failure */
}
nread = fread(buffer, 1, size, form->fp);
if(nread != size) {
/* this is the last chunk form the file, move on */
/* this is the last chunk from the file, move on */
fclose(form->fp);
form->fp = NULL;
form->data = form->data->next;
@ -1232,9 +1417,13 @@ size_t Curl_FormReader(char *buffer,
if(!form->data)
return 0; /* nothing, error, empty */
if(form->data->type == FORM_FILE)
return readfromfile(form, buffer, wantedsize);
if(form->data->type == FORM_FILE) {
gotsize = readfromfile(form, buffer, wantedsize);
if(gotsize)
/* If positive or -1, return. If zero, continue! */
return gotsize;
}
do {
if( (form->data->length - form->sent ) > wantedsize - gotsize) {
@ -1256,7 +1445,7 @@ size_t Curl_FormReader(char *buffer,
form->data = form->data->next; /* advance */
} while(form->data && (form->data->type == FORM_DATA));
} while(form->data && (form->data->type != FORM_FILE));
/* If we got an empty line and we have more data, we proceed to the next
line immediately to avoid returning zero before we've reached the end.
This is the bug reported November 22 1999 on curl 6.3. (Daniel) */
@ -1323,7 +1512,7 @@ int main()
char value5[] = "value for PTRCONTENTS + CONTENTSLENGTH";
char value6[] = "value for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE";
char value7[] = "inet_ntoa_r.h";
char value8[] = "Makefile.b32.resp";
char value8[] = "Makefile.b32";
char type2[] = "image/gif";
char type6[] = "text/plain";
char type7[] = "text/html";
@ -1332,7 +1521,8 @@ int main()
int value5length = strlen(value4);
int value6length = strlen(value5);
int errors = 0;
int size;
CURLcode rc;
size_t size;
size_t nread;
char buffer[4096];
struct curl_httppost *httppost=NULL;
@ -1408,7 +1598,14 @@ int main()
CURLFORM_END))
++errors;
form=Curl_getFormData(httppost, &size);
rc = Curl_getFormData(&form, httppost, NULL, &size);
if(rc != CURLE_OK) {
if(rc != CURLE_READ_ERROR) {
const char *errortext = curl_easy_strerror(rc);
fprintf(stdout, "\n==> Curl_getFormData error: %s\n", errortext);
}
return 0;
}
Curl_FormInit(&formread, form);
@ -1416,7 +1613,7 @@ int main()
nread = Curl_FormReader(buffer, 1, sizeof(buffer),
(FILE *)&formread);
if(-1 == nread)
if(nread < 1)
break;
fwrite(buffer, nread, 1, stdout);
} while(1);
@ -1430,7 +1627,7 @@ int main()
return 0;
}
#endif
#endif /* _FORM_DEBUG */
#else /* CURL_DISABLE_HTTP */
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
@ -1442,6 +1639,15 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
return CURL_FORMADD_DISABLED;
}
int curl_formget(struct curl_httppost *form, void *arg,
curl_formget_callback append)
{
(void) form;
(void) arg;
(void) append;
return CURL_FORMADD_DISABLED;
}
void curl_formfree(struct curl_httppost *form)
{
(void)form;
@ -1450,6 +1656,8 @@ void curl_formfree(struct curl_httppost *form)
#endif /* CURL_DISABLE_HTTP */
#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
/*
* Curl_FormBoundary() creates a suitable boundary string and returns an
* allocated one. This is also used by SSL-code so it must be present even
@ -1458,18 +1666,18 @@ void curl_formfree(struct curl_httppost *form)
char *Curl_FormBoundary(void)
{
char *retstring;
static int randomizer=0; /* this is just so that two boundaries within
static int randomizer; /* this is just so that two boundaries within
the same form won't be identical */
size_t i;
static char table16[]="abcdef0123456789";
static const char table16[]="abcdef0123456789";
retstring = (char *)malloc(BOUNDARY_LENGTH+1);
if(!retstring)
return NULL; /* failed */
srand((unsigned int)((time(NULL)+randomizer++))); /* seed */
srand((unsigned int)time(NULL)+randomizer++); /* seed */
strcpy(retstring, "----------------------------");
@ -1482,3 +1690,5 @@ char *Curl_FormBoundary(void)
return retstring;
}
#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */

View File

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -25,8 +25,10 @@
***************************************************************************/
enum formtype {
FORM_DATA, /* regular data */
FORM_FILE /* 'line' points to a file name we should read from */
FORM_DATA, /* form metadata (convert to network encoding if necessary) */
FORM_CONTENT, /* form content (never convert) */
FORM_FILE /* 'line' points to a file name we should read from
to create the form data (never convert) */
};
/* plain and simple linked list with lines to send */
@ -69,6 +71,7 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata );
CURLcode
Curl_getFormData(struct FormData **,
struct curl_httppost *post,
const char *custom_contenttype,
curl_off_t *size);
/* fread() emulation */
@ -86,7 +89,9 @@ char *Curl_formpostheader(void *formp, size_t *len);
char *Curl_FormBoundary(void);
void Curl_formclean(struct FormData *);
void Curl_formclean(struct FormData **);
CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,18 @@
#ifndef __FTP_H
#define __FTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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.
@ -24,14 +24,20 @@
***************************************************************************/
#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(struct connectdata *conn, bool *done);
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode, bool premature);
CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done);
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
CURLcode Curl_nbftpsendf(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
CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done);
int Curl_ftp_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
CURLcode Curl_ftp_doing(struct connectdata *conn,
bool *dophase_done);
#endif /* CURL_DISABLE_FTP */
#endif /* __FTP_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +0,0 @@
/*
** 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));

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -27,24 +27,22 @@
#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 "memory.h"
#include "memdebug.h"
static
char *GetEnv(const char *variable)
{
#ifdef _WIN32_WCE
return NULL;
#else
#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';
@ -62,6 +60,7 @@ char *GetEnv(const char *variable)
#endif
#endif
return (env && env[0])?strdup(env):NULL;
#endif
}
char *curl_getenv(const char *v)

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -32,13 +32,14 @@
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "curl_memory.h"
#include "memory.h"
#include "sslgen.h"
/* Make this the last #include */
#include "memdebug.h"
/*
* This is supposed to be called in the beginning of a permform() session
* This is supposed to be called in the beginning of a perform() session
* and should reset all session-info variables
*/
CURLcode Curl_initinfo(struct SessionHandle *data)
@ -56,13 +57,14 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
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;
info->numconnects = 0;
return CURLE_OK;
}
@ -72,13 +74,19 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
long *param_longp=NULL;
double *param_doublep=NULL;
char **param_charp=NULL;
struct curl_slist **param_slistp=NULL;
char buf;
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
va_start(arg, info);
switch(info&CURLINFO_TYPEMASK) {
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
case CURLINFO_STRING:
param_charp = va_arg(arg, char **);
param_charp = va_arg(arg, char **);
if(NULL == param_charp)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
@ -92,8 +100,13 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
if(NULL == param_doublep)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLINFO_SLIST:
param_slistp = va_arg(arg, struct curl_slist **);
if(NULL == param_slistp)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
switch(info) {
case CURLINFO_EFFECTIVE_URL:
*param_charp = data->change.url?data->change.url:(char *)"";
@ -159,7 +172,7 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
*param_charp = data->info.contenttype;
break;
case CURLINFO_PRIVATE:
*param_charp = data->set.private;
*param_charp = data->set.private_data;
break;
case CURLINFO_HTTPAUTH_AVAIL:
*param_longp = data->info.httpauthavail;
@ -167,6 +180,53 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
case CURLINFO_PROXYAUTH_AVAIL:
*param_longp = data->info.proxyauthavail;
break;
case CURLINFO_OS_ERRNO:
*param_longp = data->state.os_errno;
break;
case CURLINFO_NUM_CONNECTS:
*param_longp = data->info.numconnects;
break;
case CURLINFO_SSL_ENGINES:
*param_slistp = Curl_ssl_engines_list(data);
break;
case CURLINFO_COOKIELIST:
*param_slistp = Curl_cookie_list(data);
break;
case CURLINFO_FTP_ENTRY_PATH:
/* Return the entrypath string from the most recent connection.
This pointer was copied from the connectdata structure by FTP.
The actual string may be free()ed by subsequent libcurl calls so
it must be copied to a safer area before the next libcurl call.
Callers must never free it themselves. */
*param_charp = data->state.most_recent_ftp_entrypath;
break;
case CURLINFO_LASTSOCKET:
if((data->state.lastconnect != -1) &&
(data->state.connc->connects[data->state.lastconnect] != NULL)) {
struct connectdata *c = data->state.connc->connects
[data->state.lastconnect];
*param_longp = c->sock[FIRSTSOCKET];
/* we have a socket connected, let's determine if the server shut down */
/* determine if ssl */
if(c->ssl[FIRSTSOCKET].use) {
/* use the SSL context */
if (!Curl_ssl_check_cxn(c))
*param_longp = -1; /* FIN received */
}
/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
#ifdef MSG_PEEK
else {
/* use the socket */
if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
*param_longp = -1; /* FIN received */
}
}
#endif
}
else
*param_longp = -1;
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}

640
Utilities/cmcurl/gtls.c Normal file
View File

@ -0,0 +1,640 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, 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$
***************************************************************************/
/*
* Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
* but sslgen.c should ever call or use these functions.
*
* Note: don't use the GnuTLS' *_t variable type names in this source code,
* since they were not present in 1.0.X.
*/
#include "setup.h"
#ifdef USE_GNUTLS
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "gtls.h"
#include "sslgen.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
#ifdef GTLSDEBUG
static void tls_log_func(int level, const char *str)
{
fprintf(stderr, "|<%d>| %s", level, str);
}
#endif
/*
* Custom push and pull callback functions used by GNU TLS to read and write
* to the socket. These functions are simple wrappers to send() and recv()
* (although here using the sread/swrite macros as defined by setup_once.h).
* We use custom functions rather than the GNU TLS defaults because it allows
* us to get specific about the fourth "flags" argument, and to use arbitrary
* private data with gnutls_transport_set_ptr if we wish.
*/
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
return swrite(s, buf, len);
}
static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{
return sread(s, buf, len);
}
/* Global GnuTLS init, called from Curl_ssl_init() */
int Curl_gtls_init(void)
{
gnutls_global_init();
#ifdef GTLSDEBUG
gnutls_global_set_log_function(tls_log_func);
gnutls_global_set_log_level(2);
#endif
return 1;
}
int Curl_gtls_cleanup(void)
{
gnutls_global_deinit();
return 1;
}
static void showtime(struct SessionHandle *data,
const char *text,
time_t stamp)
{
struct tm *tm;
#ifdef HAVE_GMTIME_R
struct tm buffer;
tm = (struct tm *)gmtime_r(&stamp, &buffer);
#else
tm = gmtime(&stamp);
#endif
snprintf(data->state.buffer,
BUFSIZE,
"\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
text,
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
Curl_month[tm->tm_mon],
tm->tm_year + 1900,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
infof(data, "%s", data->state.buffer);
}
/* this function does a BLOCKING SSL/TLS (re-)handshake */
static CURLcode handshake(struct connectdata *conn,
gnutls_session session,
int sockindex,
bool duringconnect)
{
struct SessionHandle *data = conn->data;
int rc;
do {
rc = gnutls_handshake(session);
if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
long timeout_ms = DEFAULT_CONNECT_TIMEOUT;
long has_passed;
if(duringconnect && data->set.connecttimeout)
timeout_ms = data->set.connecttimeout*1000;
if(data->set.timeout) {
/* get the strictest timeout of the ones converted to milliseconds */
if((data->set.timeout*1000) < timeout_ms)
timeout_ms = data->set.timeout*1000;
}
/* Evaluate in milliseconds how much time that has passed */
has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
/* 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, "SSL connection timeout");
return CURLE_OPERATION_TIMEOUTED;
}
rc = Curl_select(conn->sock[sockindex],
conn->sock[sockindex], (int)timeout_ms);
if(rc > 0)
/* reabable or writable, go loop*/
continue;
else if(0 == rc) {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
else {
/* anything that gets here is fatally bad */
failf(data, "select on SSL socket, errno: %d", Curl_sockerrno());
return CURLE_SSL_CONNECT_ERROR;
}
}
else
break;
} while(1);
if (rc < 0) {
failf(data, "gnutls_handshake() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
}
return CURLE_OK;
}
static gnutls_x509_crt_fmt do_file_type(const char *type)
{
if(!type || !type[0])
return GNUTLS_X509_FMT_PEM;
if(curl_strequal(type, "PEM"))
return GNUTLS_X509_FMT_PEM;
if(curl_strequal(type, "DER"))
return GNUTLS_X509_FMT_DER;
return -1;
}
/*
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic.
*/
CURLcode
Curl_gtls_connect(struct connectdata *conn,
int sockindex)
{
const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
struct SessionHandle *data = conn->data;
gnutls_session session;
int rc;
unsigned int cert_list_size;
const gnutls_datum *chainp;
unsigned int verify_status;
gnutls_x509_crt x509_cert;
char certbuf[256]; /* big enough? */
size_t size;
unsigned int algo;
unsigned int bits;
time_t clock;
const char *ptr;
void *ssl_sessionid;
size_t ssl_idsize;
/* GnuTLS only supports TLSv1 (and SSLv3?) */
if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
}
/* allocate a cred struct */
rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
if(rc < 0) {
failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
}
if(data->set.ssl.CAfile) {
/* set the trusted CA cert bundle file */
gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
data->set.ssl.CAfile,
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)\n",
data->set.ssl.CAfile, gnutls_strerror(rc));
if (data->set.ssl.verifypeer)
return CURLE_SSL_CACERT_BADFILE;
}
else
infof(data, "found %d certificates in %s\n",
rc, data->set.ssl.CAfile);
}
/* Initialize TLS session as a client */
rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
if(rc) {
failf(data, "gnutls_init() failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
/* convenient assign */
session = conn->ssl[sockindex].session;
/* Use default priorities */
rc = gnutls_set_default_priority(session);
if(rc < 0)
return CURLE_SSL_CONNECT_ERROR;
/* Sets the priority on the certificate types supported by gnutls. Priority
is higher for types specified before others. After specifying the types
you want, you must append a 0. */
rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
if(rc < 0)
return CURLE_SSL_CONNECT_ERROR;
if(data->set.cert) {
if( gnutls_certificate_set_x509_key_file(
conn->ssl[sockindex].cred, data->set.cert,
data->set.key != 0 ? data->set.key : data->set.cert,
do_file_type(data->set.cert_type) ) ) {
failf(data, "error reading X.509 key or certificate file");
return CURLE_SSL_CONNECT_ERROR;
}
}
/* put the credentials to the current session */
rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
conn->ssl[sockindex].cred);
/* set the connection handle (file descriptor for the socket) */
gnutls_transport_set_ptr(session,
(gnutls_transport_ptr)conn->sock[sockindex]);
/* register callback functions to send and receive data. */
gnutls_transport_set_push_function(session, Curl_gtls_push);
gnutls_transport_set_pull_function(session, Curl_gtls_pull);
/* lowat must be set to zero when using custom push and pull functions. */
gnutls_transport_set_lowat(session, 0);
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
/* we got a session id, use it! */
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
/* Informational message */
infof (data, "SSL re-using session ID\n");
}
rc = handshake(conn, session, sockindex, TRUE);
if(rc)
/* handshake() sets its own error message with failf() */
return rc;
/* This function will return the peer's raw certificate (chain) as sent by
the peer. These certificates are in raw format (DER encoded for
X.509). In case of a X.509 then a certificate list may be present. The
first certificate in the list is the peer's certificate, following the
issuer's certificate, then the issuer's issuer etc. */
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
if(!chainp) {
if(data->set.ssl.verifyhost) {
failf(data, "failed to get server cert");
return CURLE_SSL_PEER_CERTIFICATE;
}
infof(data, "\t common name: WARNING couldn't obtain\n");
}
/* This function will try to verify the peer's certificate and return its
status (trusted, invalid etc.). The value of status should be one or more
of the gnutls_certificate_status_t enumerated elements bitwise or'd. To
avoid denial of service attacks some default upper limits regarding the
certificate key size and chain size are set. To override them use
gnutls_certificate_set_verify_limits(). */
rc = gnutls_certificate_verify_peers2(session, &verify_status);
if (rc < 0) {
failf(data, "server cert verify failed: %d", rc);
return CURLE_SSL_CONNECT_ERROR;
}
/* verify_status is a bitmask of gnutls_certificate_status bits */
if(verify_status & GNUTLS_CERT_INVALID) {
if (data->set.ssl.verifypeer) {
failf(data, "server certificate verification failed. CAfile: %s",
data->set.ssl.CAfile?data->set.ssl.CAfile:"none");
return CURLE_SSL_CACERT;
}
else
infof(data, "\t server certificate verification FAILED\n");
}
else
infof(data, "\t server certificate verification OK\n");
/* initialize an X.509 certificate structure. */
gnutls_x509_crt_init(&x509_cert);
/* convert the given DER or PEM encoded Certificate to the native
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
size=sizeof(certbuf);
rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
0, /* the first and only one */
FALSE,
certbuf,
&size);
if(rc) {
infof(data, "error fetching CN from cert:%s\n",
gnutls_strerror(rc));
}
/* This function will check if the given certificate's subject matches the
given hostname. This is a basic implementation of the matching described
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
alternative name PKIX extension. Returns non zero on success, and zero on
failure. */
rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
if(!rc) {
if (data->set.ssl.verifyhost > 1) {
failf(data, "SSL: certificate subject name (%s) does not match "
"target host name '%s'", certbuf, conn->host.dispname);
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_PEER_CERTIFICATE;
}
else
infof(data, "\t common name: %s (does not match '%s')\n",
certbuf, conn->host.dispname);
}
else
infof(data, "\t common name: %s (matched)\n", certbuf);
/* Show:
- ciphers used
- subject
- start date
- expire date
- common name
- issuer
*/
/* public key algorithm's parameters */
algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
infof(data, "\t certificate public key: %s\n",
gnutls_pk_algorithm_get_name(algo));
/* version of the X.509 certificate. */
infof(data, "\t certificate version: #%d\n",
gnutls_x509_crt_get_version(x509_cert));
size = sizeof(certbuf);
gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
infof(data, "\t subject: %s\n", certbuf);
clock = gnutls_x509_crt_get_activation_time(x509_cert);
showtime(data, "start date", clock);
clock = gnutls_x509_crt_get_expiration_time(x509_cert);
showtime(data, "expire date", clock);
size = sizeof(certbuf);
gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
infof(data, "\t issuer: %s\n", certbuf);
gnutls_x509_crt_deinit(x509_cert);
/* compression algorithm (if any) */
ptr = gnutls_compression_get_name(gnutls_compression_get(session));
/* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
infof(data, "\t compression: %s\n", ptr);
/* the name of the cipher used. ie 3DES. */
ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
infof(data, "\t cipher: %s\n", ptr);
/* the MAC algorithms name. ie SHA1 */
ptr = gnutls_mac_get_name(gnutls_mac_get(session));
infof(data, "\t MAC: %s\n", ptr);
if(!ssl_sessionid) {
/* this session was not previously in the cache, add it now */
/* get the session ID data size */
gnutls_session_get_data(session, NULL, &ssl_idsize);
ssl_sessionid = malloc(ssl_idsize); /* get a buffer for it */
if(ssl_sessionid) {
/* extract session ID to the allocated buffer */
gnutls_session_get_data(session, ssl_sessionid, &ssl_idsize);
/* store this session id */
return Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_idsize);
}
}
return CURLE_OK;
}
/* return number of sent (non-SSL) bytes */
ssize_t Curl_gtls_send(struct connectdata *conn,
int sockindex,
void *mem,
size_t len)
{
ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
if(rc < 0 ) {
if(rc == GNUTLS_E_AGAIN)
return 0; /* EWOULDBLOCK equivalent */
rc = -1; /* generic error code for send failure */
}
return rc;
}
void Curl_gtls_close_all(struct SessionHandle *data)
{
/* FIX: make the OpenSSL code more generic and use parts of it here */
(void)data;
}
static void close_one(struct connectdata *conn,
int index)
{
if(conn->ssl[index].session) {
gnutls_bye(conn->ssl[index].session, GNUTLS_SHUT_RDWR);
gnutls_deinit(conn->ssl[index].session);
}
gnutls_certificate_free_credentials(conn->ssl[index].cred);
}
void Curl_gtls_close(struct connectdata *conn)
{
if(conn->ssl[0].use)
close_one(conn, 0);
if(conn->ssl[1].use)
close_one(conn, 1);
}
/*
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
{
int result;
int retval = 0;
struct SessionHandle *data = conn->data;
int done = 0;
ssize_t nread;
char buf[120];
/* This has only been tested on the proftpd server, and the mod_tls code
sends a close notify alert without waiting for a close notify alert in
response. Thus we wait for a close notify alert from the server, but
we do not send one. Let's hope other servers do the same... */
if(conn->ssl[sockindex].session) {
while(!done) {
int what = Curl_select(conn->sock[sockindex],
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
notify alert from the server */
result = gnutls_record_recv(conn->ssl[sockindex].session,
buf, sizeof(buf));
switch(result) {
case 0:
/* This is the expected response. There was no data but only
the close notify alert */
done = 1;
break;
case GNUTLS_E_AGAIN:
case GNUTLS_E_INTERRUPTED:
infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
break;
default:
retval = -1;
done = 1;
break;
}
}
else if(0 == what) {
/* timeout */
failf(data, "SSL shutdown timeout");
done = 1;
break;
}
else {
/* anything that gets here is fatally bad */
failf(data, "select on SSL socket, errno: %d", Curl_sockerrno());
retval = -1;
done = 1;
}
}
gnutls_deinit(conn->ssl[sockindex].session);
}
gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
conn->ssl[sockindex].session = NULL;
conn->ssl[sockindex].use = FALSE;
return retval;
}
/*
* If the read would block we return -1 and set 'wouldblock' to TRUE.
* Otherwise we return the amount of data read. Other errors should return -1
* and set 'wouldblock' to FALSE.
*/
ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
bool *wouldblock)
{
ssize_t ret;
ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*wouldblock = TRUE;
return -1;
}
if(ret == GNUTLS_E_REHANDSHAKE) {
/* BLOCKING call, this is bad but a work-around for now. Fixing this "the
proper way" takes a whole lot of work. */
CURLcode rc = handshake(conn, conn->ssl[num].session, num, FALSE);
if(rc)
/* handshake() writes error message on its own */
return rc;
*wouldblock = TRUE; /* then return as if this was a wouldblock */
return -1;
}
*wouldblock = FALSE;
if (!ret) {
failf(conn->data, "Peer closed the TLS connection");
return -1;
}
if (ret < 0) {
failf(conn->data, "GnuTLS recv error (%d): %s",
(int)ret, gnutls_strerror(ret));
return -1;
}
return ret;
}
void Curl_gtls_session_free(void *ptr)
{
free(ptr);
}
size_t Curl_gtls_version(char *buffer, size_t size)
{
return snprintf(buffer, size, " GnuTLS/%s", gnutls_check_version(NULL));
}
#endif /* USE_GNUTLS */

46
Utilities/cmcurl/gtls.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef __GTLS_H
#define __GTLS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, 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_gtls_init(void);
int Curl_gtls_cleanup(void);
CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
/* tell GnuTLS to close down all open information regarding connections (and
thus session ID caching etc) */
void Curl_gtls_close_all(struct SessionHandle *data);
void Curl_gtls_close(struct connectdata *conn); /* close a SSL connection */
/* return number of sent (non-SSL) bytes */
ssize_t Curl_gtls_send(struct connectdata *conn, int sockindex,
void *mem, size_t len);
ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
bool *wouldblock);
void Curl_gtls_session_free(void *ptr);
size_t Curl_gtls_version(char *buffer, size_t size);
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -28,7 +28,7 @@
#include "hash.h"
#include "llist.h"
#include "curl_memory.h"
#include "memory.h"
/* this must be the last include file */
#include "memdebug.h"
@ -50,12 +50,11 @@ hash_str(const char *key, size_t key_length)
static void
hash_element_dtor(void *user, void *element)
{
curl_hash *h = (curl_hash *) user;
curl_hash_element *e = (curl_hash_element *) element;
struct curl_hash *h = (struct curl_hash *) user;
struct curl_hash_element *e = (struct curl_hash_element *) element;
if (e->key) {
if (e->key)
free(e->key);
}
h->dtor(e->ptr);
@ -64,7 +63,7 @@ hash_element_dtor(void *user, void *element)
/* return 1 on error, 0 is fine */
int
Curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
Curl_hash_init(struct curl_hash *h, int slots, curl_hash_dtor dtor)
{
int i;
@ -72,7 +71,7 @@ Curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
h->size = 0;
h->slots = slots;
h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *));
h->table = (struct curl_llist **) malloc(slots * sizeof(struct curl_llist *));
if(h->table) {
for (i = 0; i < slots; ++i) {
h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
@ -89,12 +88,12 @@ Curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
return 1; /* failure */
}
curl_hash *
struct curl_hash *
Curl_hash_alloc(int slots, curl_hash_dtor dtor)
{
curl_hash *h;
struct curl_hash *h;
h = (curl_hash *) malloc(sizeof(curl_hash));
h = (struct curl_hash *) malloc(sizeof(struct curl_hash));
if (h) {
if(Curl_hash_init(h, slots, dtor)) {
/* failure */
@ -118,15 +117,18 @@ hash_key_compare(char *key1, size_t key1_len, char *key2, size_t key2_len)
return 0;
}
static curl_hash_element *
static struct 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));
struct curl_hash_element *he =
(struct curl_hash_element *) malloc(sizeof(struct curl_hash_element));
if(he) {
char *dup = strdup(key);
char *dup = malloc(key_len);
if(dup) {
/* copy the key */
memcpy(dup, key, key_len);
he->key = dup;
he->key_len = key_len;
he->ptr = (void *) p;
@ -147,14 +149,14 @@ mk_hash_element(char *key, size_t key_len, const void *p)
/* 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_add(struct 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);
struct curl_hash_element *he;
struct curl_llist_element *le;
struct curl_llist *l = FETCH_LIST(h, key, key_len);
for (le = l->head; le; le = le->next) {
he = (curl_hash_element *) le->ptr;
he = (struct 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 */
@ -180,16 +182,31 @@ Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p)
return NULL; /* failure */
}
void *
Curl_hash_pick(curl_hash *h, char *key, size_t key_len)
/* remove the identified hash entry, returns non-zero on failure */
int Curl_hash_delete(struct 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);
struct curl_llist_element *le;
struct curl_hash_element *he;
struct curl_llist *l = FETCH_LIST(h, key, key_len);
for (le = l->head;
le;
le = le->next) {
for (le = l->head; le; le = le->next) {
he = le->ptr;
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
return 0;
}
}
return 1;
}
void *
Curl_hash_pick(struct curl_hash *h, char *key, size_t key_len)
{
struct curl_llist_element *le;
struct curl_hash_element *he;
struct 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;
@ -204,7 +221,7 @@ void
Curl_hash_apply(curl_hash *h, void *user,
void (*cb)(void *user, void *ptr))
{
curl_llist_element *le;
struct curl_llist_element *le;
int i;
for (i = 0; i < h->slots; ++i) {
@ -219,7 +236,7 @@ Curl_hash_apply(curl_hash *h, void *user,
#endif
void
Curl_hash_clean(curl_hash *h)
Curl_hash_clean(struct curl_hash *h)
{
int i;
@ -231,19 +248,19 @@ Curl_hash_clean(curl_hash *h)
}
void
Curl_hash_clean_with_criterium(curl_hash *h, void *user,
Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
int (*comp)(void *, void *))
{
curl_llist_element *le;
curl_llist_element *lnext;
curl_llist *list;
struct curl_llist_element *le;
struct curl_llist_element *lnext;
struct 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;
struct 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)) {
@ -256,7 +273,7 @@ Curl_hash_clean_with_criterium(curl_hash *h, void *user,
}
void
Curl_hash_destroy(curl_hash *h)
Curl_hash_destroy(struct curl_hash *h)
{
if (!h)
return;
@ -265,3 +282,34 @@ Curl_hash_destroy(curl_hash *h)
free(h);
}
#if 0 /* useful function for debugging hashes and their contents */
void Curl_hash_print(struct curl_hash *h,
void (*func)(void *))
{
int i;
struct curl_llist_element *le;
struct curl_llist *list;
struct curl_hash_element *he;
if (!h)
return;
fprintf(stderr, "=Hash dump=\n");
for (i = 0; i < h->slots; i++) {
list = h->table[i];
le = list->head; /* get first list entry */
if(le) {
fprintf(stderr, "index %d:", i);
while(le) {
he = le->ptr;
if(func)
func(he->ptr);
else
fprintf(stderr, " [%p]", he->ptr);
le = le->next;
}
fprintf(stderr, "\n");
}
}
}
#endif

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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
@ -31,30 +31,31 @@
typedef void (*curl_hash_dtor)(void *);
typedef struct _curl_hash {
curl_llist **table;
struct curl_hash {
struct curl_llist **table;
curl_hash_dtor dtor;
int slots;
size_t size;
} curl_hash;
int slots;
size_t size;
};
typedef struct _curl_hash_element {
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,
int Curl_hash_init(struct curl_hash *, int, curl_hash_dtor);
struct curl_hash *Curl_hash_alloc(int, curl_hash_dtor);
void *Curl_hash_add(struct curl_hash *, char *, size_t, void *);
int Curl_hash_delete(struct curl_hash *h, char *key, size_t key_len);
void *Curl_hash_pick(struct curl_hash *, char *, size_t);
void Curl_hash_apply(struct 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);
int Curl_hash_count(struct curl_hash *h);
void Curl_hash_clean(struct curl_hash *h);
void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
int (*comp)(void *, void *));
void Curl_hash_destroy(struct curl_hash *h);
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -24,13 +24,10 @@
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef NEED_MALLOC_H
#include <malloc.h>
#else
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -57,13 +54,12 @@
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
@ -79,6 +75,8 @@
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "multiif.h"
#include "connect.h" /* for the Curl_sockerrno() proto */
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -87,7 +85,7 @@
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -99,7 +97,7 @@
#ifdef CURLRES_ARES
/*
* Curl_fdset() is called when someone from the outside world (using
* Curl_resolv_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.
@ -107,17 +105,26 @@
* Returns: CURLE_OK always!
*/
CURLcode Curl_fdset(struct connectdata *conn,
fd_set *read_fd_set,
fd_set *write_fd_set,
int *max_fdp)
int Curl_resolv_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
int max = ares_fds(conn->data->state.areschannel,
read_fd_set, write_fd_set);
*max_fdp = max;
struct timeval maxtime;
struct timeval timeout;
int max = ares_getsock(conn->data->state.areschannel,
(int *)socks, numsocks);
return CURLE_OK;
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0;
ares_timeout(conn->data->state.areschannel, &maxtime, &timeout);
Curl_expire(conn->data,
(timeout.tv_sec * 1000) + (timeout.tv_usec/1000) );
return max;
}
/*
@ -213,7 +220,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
break;
tvp = ares_timeout(data->state.areschannel, &store, &tv);
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
if (count < 0 && errno != EINVAL)
if (count < 0 && Curl_sockerrno() != EINVAL)
break;
ares_process(data->state.areschannel, &read_fds, &write_fds);
@ -249,7 +256,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
/* close the connection, since we can't return failure here without
cleaning up this connection properly */
Curl_disconnect(conn);
conn->bits.close = TRUE;
}
return rc;
@ -264,7 +271,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
* Curl_freeaddrinfo(), nothing else.
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
const char *hostname,
int port,
int *waitp)
{
@ -291,11 +298,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname(data->state.areschannel, hostname, PF_INET,
Curl_addrinfo4_callback, conn);
(ares_host_callback)Curl_addrinfo4_callback, conn);
*waitp = TRUE; /* please wait for the response */
}
return NULL; /* no struct yet */
}
#endif /* CURLRES_ARES */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -24,13 +24,10 @@
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef NEED_MALLOC_H
#include <malloc.h>
#else
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -57,21 +54,15 @@
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#ifdef HAVE_PROCESS_H
#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"
@ -87,7 +78,7 @@
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -108,21 +99,21 @@
*
* The storage operation locks and unlocks the DNS cache.
*/
static void addrinfo_callback(void *arg, /* "struct connectdata *" */
int status,
void *addr)
static CURLcode addrinfo_callback(void *arg, /* "struct connectdata *" */
int status,
void *addr)
{
struct connectdata *conn = (struct connectdata *)arg;
struct Curl_dns_entry *dns = NULL;
CURLcode rc = CURLE_OK;
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.
* IPv4/ares: Curl_addrinfo_copy() copies the address and returns an
* allocated version.
*
* IPv6: Curl_addrinfo_copy() returns the input pointer!
*/
@ -136,34 +127,47 @@ static void addrinfo_callback(void *arg, /* "struct connectdata *" */
dns = Curl_cache_addr(data, ai,
conn->async.hostname,
conn->async.port);
if(!dns)
if(!dns) {
/* failed to store, cleanup and return error */
Curl_freeaddrinfo(ai);
rc = CURLE_OUT_OF_MEMORY;
}
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
else
rc = CURLE_OUT_OF_MEMORY;
}
conn->async.dns = dns;
/* Set async.done TRUE last in this function since it may be used multi-
threaded and once this is TRUE the other thread may read fields from the
async struct */
conn->async.done = TRUE;
/* ipv4: The input hostent struct will be freed by ares when we return from
this function */
return rc;
}
void Curl_addrinfo4_callback(void *arg, /* "struct connectdata *" */
int status,
struct hostent *hostent)
CURLcode Curl_addrinfo4_callback(void *arg, /* "struct connectdata *" */
int status,
struct hostent *hostent)
{
addrinfo_callback(arg, status, hostent);
return addrinfo_callback(arg, status, hostent);
}
#ifdef CURLRES_IPV6
void Curl_addrinfo6_callback(void *arg, /* "struct connectdata *" */
int status,
struct addrinfo *ai)
CURLcode Curl_addrinfo6_callback(void *arg, /* "struct connectdata *" */
int status,
struct addrinfo *ai)
{
addrinfo_callback(arg, status, ai);
/* NOTE: for CURLRES_ARES, the 'ai' argument is really a
* 'struct hostent' pointer.
*/
return addrinfo_callback(arg, status, ai);
}
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -24,13 +24,10 @@
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef NEED_MALLOC_H
#include <malloc.h>
#else
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -57,21 +54,15 @@
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#ifdef HAVE_PROCESS_H
#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"
@ -88,7 +79,7 @@
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -105,8 +96,7 @@
* 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.
* asynchronous name resolves. 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
@ -131,7 +121,7 @@
*/
/* These two symbols are for the global DNS cache */
static curl_hash hostname_cache;
static struct curl_hash hostname_cache;
static int host_cache_initialized;
static void freednsentry(void *freethis);
@ -152,7 +142,7 @@ void Curl_global_host_cache_init(void)
/*
* Return a pointer to the global cache
*/
curl_hash *Curl_global_host_cache_get(void)
struct curl_hash *Curl_global_host_cache_get(void)
{
return &hostname_cache;
}
@ -174,20 +164,11 @@ void Curl_global_host_cache_dtor(void)
int Curl_num_addresses(const Curl_addrinfo *addr)
{
int i;
for (i = 0; addr; addr = addr->ai_next, i++);
for (i = 0; addr; addr = addr->ai_next, i++)
; /* empty loop */
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
@ -198,17 +179,13 @@ int Curl_num_addresses(const Curl_addrinfo *addr)
const char *Curl_printable_address(const Curl_addrinfo *ip,
char *buf, size_t bufsize)
{
const void *ip4 = &((const struct sockaddr_in*)ip->ai_addr)->sin_addr;
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);
const void *ip6 = &((const struct sockaddr_in6*)ip->ai_addr)->sin6_addr;
#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);
}
@ -218,7 +195,7 @@ const char *Curl_printable_address(const Curl_addrinfo *ip,
* the DNS caching.
*/
static char *
create_hostcache_id(char *server, int port)
create_hostcache_id(const char *server, int port)
{
/* create and return the new allocated entry */
return aprintf("%s:%d", server, port);
@ -257,7 +234,7 @@ hostcache_timestamp_remove(void *datap, void *hc)
* 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)
hostcache_prune(struct curl_hash *hostcache, int cache_timeout, time_t now)
{
struct hostcache_prune_data user;
@ -277,8 +254,9 @@ void Curl_hostcache_prune(struct SessionHandle *data)
{
time_t now;
if(data->set.dns_cache_timeout == -1)
/* cache forever means never prune! */
if((data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
/* cache forever means never prune, and NULL hostcache means
we can't do it */
return;
if(data->share)
@ -287,7 +265,7 @@ void Curl_hostcache_prune(struct SessionHandle *data)
time(&now);
/* Remove outdated and unused entries from the hostcache */
hostcache_prune(data->hostcache,
hostcache_prune(data->dns.hostcache,
data->set.dns_cache_timeout,
now);
@ -295,6 +273,39 @@ void Curl_hostcache_prune(struct SessionHandle *data)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
static int
remove_entry_if_stale(struct SessionHandle *data, struct Curl_dns_entry *dns)
{
struct hostcache_prune_data user;
if( !dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
/* cache forever means never prune, and NULL hostcache means
we can't do it */
return 0;
time(&user.now);
user.cache_timeout = data->set.dns_cache_timeout;
if ( !hostcache_timestamp_remove(&user,dns) )
return 0;
/* ok, we do need to clear the cache. although we need to remove just a
single entry we clean the entire hash, as no explicit delete function
is provided */
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
Curl_hash_clean_with_criterium(data->dns.hostcache,
(void *) &user,
hostcache_timestamp_remove);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
return 1;
}
#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
@ -315,7 +326,7 @@ sigjmp_buf curl_jmpenv;
struct Curl_dns_entry *
Curl_cache_addr(struct SessionHandle *data,
Curl_addrinfo *addr,
char *hostname,
const char *hostname,
int port)
{
char *entry_id;
@ -332,7 +343,7 @@ Curl_cache_addr(struct SessionHandle *data,
entry_len = strlen(entry_id);
/* Create a new cache entry */
dns = (struct Curl_dns_entry *) malloc(sizeof(struct Curl_dns_entry));
dns = (struct Curl_dns_entry *) calloc(sizeof(struct Curl_dns_entry), 1);
if (!dns) {
free(entry_id);
return NULL;
@ -344,7 +355,8 @@ Curl_cache_addr(struct SessionHandle *data,
/* 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);
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
(void *)dns);
if(!dns2) {
/* Major badness, run away. */
free(dns);
@ -381,31 +393,30 @@ Curl_cache_addr(struct SessionHandle *data,
*/
int Curl_resolv(struct connectdata *conn,
char *hostname,
const char *hostname,
int port,
struct Curl_dns_entry **entry)
{
char *entry_id;
char *entry_id = NULL;
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;
if(!data->set.no_signal) {
if (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);
@ -419,7 +430,7 @@ int Curl_resolv(struct connectdata *conn,
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);
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@ -427,6 +438,13 @@ int Curl_resolv(struct connectdata *conn,
/* free the allocated entry_id again */
free(entry_id);
/* See whether the returned entry is stale. Deliberately done after the
locked block */
if ( remove_entry_if_stale(data,dns) )
dns = NULL; /* the memory deallocation is being handled by the hash */
rc = CURLRESOLV_ERROR; /* default to failure */
if (!dns) {
/* The entry was not in the cache. Resolve it to IP address */
@ -474,7 +492,11 @@ int Curl_resolv(struct connectdata *conn,
}
}
else {
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns->inuse++; /* we use it! */
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
rc = CURLRESOLV_RESOLVED;
}
@ -516,7 +538,7 @@ static void freednsentry(void *freethis)
/*
* Curl_mk_dnscache() creates a new DNS cache and returns the handle for it.
*/
curl_hash *Curl_mk_dnscache(void)
struct curl_hash *Curl_mk_dnscache(void)
{
return Curl_hash_alloc(7, freednsentry);
}
@ -531,10 +553,84 @@ curl_hash *Curl_mk_dnscache(void)
* 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)
Curl_addrinfo *Curl_addrinfo_copy(const void *org, int port)
{
struct hostent *orig = org;
const struct hostent *orig = org;
return Curl_he2ai(orig, port);
}
#endif /* CURLRES_ADDRINFO_COPY */
/***********************************************************************
* Only for plain-ipv4 and c-ares builds
**********************************************************************/
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
/*
* 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;
}
}
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, const 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;
#ifdef _CRAYC
/* On UNICOS, s_addr is a bit field and for some reason assigning to it
* doesn't work. There must be a better fix than this ugly hack.
*/
memcpy(addrentry, &num, SIZEOF_in_addr);
#else
addrentry->s_addr = num;
#endif
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;
}
#endif

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -26,8 +26,9 @@
#include "setup.h"
#include "hash.h"
#ifdef HAVE_NETDB_H
#include <netdb.h>
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t uint32_t
#endif
/*
@ -55,14 +56,14 @@
#define CURLRES_IPV4
#endif
#ifdef CURLRES_IPV4
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
#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)) */
Curl_he2ai() function)) */
#define CURLRES_ADDRINFO_COPY
#endif
#endif /* IPv4-only */
#endif /* IPv4/ares-only */
#ifndef CURLRES_ASYNCH
#define CURLRES_SYNCH
@ -86,6 +87,8 @@
#define CURL_ASYNC_SUCCESS ARES_SUCCESS
#else
#define CURL_ASYNC_SUCCESS CURLE_OK
#define ares_cancel(x) do {} while(0)
#define ares_destroy(x) do {} while(0)
#endif
/*
@ -97,25 +100,26 @@ typedef struct addrinfo Curl_addrinfo;
/* 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;
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */
char *ai_canonname;
struct sockaddr *ai_addr;
struct Curl_addrinfo *ai_next;
};
typedef struct Curl_addrinfo Curl_addrinfo;
#endif
struct addrinfo;
struct hostent;
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);
struct curl_hash *Curl_global_host_cache_get(void);
#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
@ -137,7 +141,7 @@ struct Curl_dns_entry {
#define CURLRESOLV_ERROR -1
#define CURLRESOLV_RESOLVED 0
#define CURLRESOLV_PENDING 1
int Curl_resolv(struct connectdata *conn, char *hostname,
int Curl_resolv(struct connectdata *conn, const char *hostname,
int port, struct Curl_dns_entry **dnsentry);
/*
@ -153,7 +157,7 @@ bool Curl_ipvalid(struct SessionHandle *data);
* of arguments
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
const char *hostname,
int port,
int *waitp);
@ -162,15 +166,19 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
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);
/* Curl_resolv_getsock() 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 multi_getsock() function. 'sock' is a pointer
to an array to hold the file descriptors, with 'numsock' being the size of
that array (in number of entries). This function is supposed to return
bitmask indicating what file descriptors (referring to array indexes in the
'sock' array) to wait for, read/write. */
int Curl_resolv_getsock(struct connectdata *conn, curl_socket_t *sock,
int numsocks);
/* unlock a previously resolved dns entry */
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns);
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);
@ -179,7 +187,7 @@ void Curl_scan_cache_used(void *user, void *ptr);
void Curl_freeaddrinfo(Curl_addrinfo *freeaddr);
/* make a new dns cache and return the handle */
curl_hash *Curl_mk_dnscache(void);
struct curl_hash *Curl_mk_dnscache(void);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct SessionHandle *data);
@ -190,41 +198,42 @@ 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,
int curl_dogetaddrinfo(const char *hostname, const 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,
#ifdef HAVE_GETNAMEINFO
int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
GETNAMEINFO_TYPE_ARG2 salen,
char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
GETNAMEINFO_TYPE_ARG7 flags,
int line, const char *source);
#endif
#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);
CURLcode 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);
CURLcode Curl_addrinfo6_callback(void *arg,
int status,
struct addrinfo *ai);
/* [ipv4 only] Creates a Curl_addrinfo struct from a numerical-only IP
/* [ipv4/ares only] Creates a Curl_addrinfo struct from a numerical-only IP
address */
Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname, int port);
Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port);
/* [ipv4 only] Curl_he2ai() converts a struct hostent to a Curl_addrinfo chain
/* [ipv4/ares 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);
Curl_addrinfo *Curl_he2ai(const struct hostent *, int port);
/* Clone a Curl_addrinfo struct, works protocol independently */
Curl_addrinfo *Curl_addrinfo_copy(void *orig, int port);
Curl_addrinfo *Curl_addrinfo_copy(const void *orig, int port);
/*
* Curl_printable_address() returns a printable version of the 1st address
@ -241,7 +250,14 @@ const char *Curl_printable_address(const Curl_addrinfo *ip,
*/
struct Curl_dns_entry *
Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
char *hostname, int port);
const char *hostname, int port);
/*
* Curl_destroy_thread_data() cleans up async resolver data.
* Complementary of ares_destroy.
*/
struct Curl_async; /* forward-declaration */
void Curl_destroy_thread_data(struct Curl_async *async);
#ifndef INADDR_NONE
#define CURL_INADDR_NONE (in_addr_t) ~0

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -26,11 +26,9 @@
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef NEED_MALLOC_H
#include <malloc.h>
#else
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -57,21 +55,15 @@
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#ifdef HAVE_PROCESS_H
#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"
@ -79,6 +71,7 @@
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "inet_pton.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -87,7 +80,7 @@
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -95,23 +88,6 @@
* 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.
@ -125,57 +101,13 @@ bool Curl_ipvalid(struct SessionHandle *data)
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.
* The original code to this function was 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
@ -188,7 +120,7 @@ Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname, int port)
*
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
const char *hostname,
int port,
int *waitp)
{
@ -202,11 +134,9 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
*waitp = 0; /* don't wait, we act synchronously */
in=inet_addr(hostname);
if (in != CURL_INADDR_NONE) {
if(1 == Curl_inet_pton(AF_INET, hostname, &in))
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(in, hostname, port);
}
#if defined(HAVE_GETHOSTBYNAME_R)
/*
@ -370,55 +300,55 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
}
#endif /* CURLRES_SYNCH */
#endif /* CURLRES_IPV4 */
/*
* 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.
*
* Curl_addrinfo defined in "lib/hostip.h"
*
* struct Curl_addrinfo {
* int ai_flags;
* int ai_family;
* int ai_socktype;
* int ai_protocol;
* socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
* char *ai_canonname;
* struct sockaddr *ai_addr;
* struct Curl_addrinfo *ai_next;
* };
*
* hostent defined in <netdb.h>
*
* struct hostent {
* char *h_name;
* char **h_aliases;
* int h_addrtype;
* int h_length;
* char **h_addr_list;
* };
*
* for backward compatibility:
*
* #define h_addr h_addr_list[0]
*/
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 *Curl_he2ai(const struct hostent *he, int port)
{
Curl_addrinfo *ai;
Curl_addrinfo *prevai = NULL;
Curl_addrinfo *firstai = NULL;
struct sockaddr_in *addr;
int i;
union {
struct in_addr *addr;
char* list;
} curr;
union {
struct sockaddr_in* addr_in;
struct sockaddr* addr;
} address;
struct in_addr *curr;
if(!he)
/* no input == no output! */
return NULL;
for(i=0; (curr.list = he->h_addr_list[i]); i++) {
for(i=0; (curr = (struct in_addr *)he->h_addr_list[i]) != NULL; i++) {
ai = calloc(1, sizeof(Curl_addrinfo) + sizeof(struct sockaddr_in));
@ -434,23 +364,26 @@ Curl_addrinfo *Curl_he2ai(struct hostent *he, int port)
prevai->ai_next = ai;
ai->ai_family = AF_INET; /* we only support this */
ai->ai_socktype = SOCK_STREAM; /* we only support this */
/* we return all names as STREAM, so when using this address for TFTP
the type must be ignored and conn->socktype be used instead! */
ai->ai_socktype = SOCK_STREAM;
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);
ai->ai_addr = (struct sockaddr *) ((char*)ai + sizeof(Curl_addrinfo));
/* leave the rest of the struct filled with zero */
address.addr = ai->ai_addr; /* storage area for this info */
addr = (struct sockaddr_in *)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);
memcpy((char *)&(addr->sin_addr), curr, sizeof(struct in_addr));
addr->sin_family = he->h_addrtype;
addr->sin_port = htons((unsigned short)port);
prevai = ai;
}
return firstai;
}
#endif /* CURLRES_IPV4 */

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -24,13 +24,10 @@
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef NEED_MALLOC_H
#include <malloc.h>
#else
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -57,21 +54,15 @@
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#ifdef HAVE_PROCESS_H
#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"
@ -79,6 +70,8 @@
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "inet_pton.h"
#include "connect.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -87,7 +80,7 @@
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -95,6 +88,7 @@
* Only for ipv6-enabled builds
**********************************************************************/
#ifdef CURLRES_IPV6
#ifndef CURLRES_ARES
/*
* This is a wrapper function for freeing name information in a protocol
* independent way. This takes care of using the appropriate underlaying
@ -111,19 +105,20 @@ void Curl_freeaddrinfo(Curl_addrinfo *p)
* 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)
Curl_addrinfo *Curl_addrinfo_copy(const void *orig, int port)
{
(void) port;
return source;
return (Curl_addrinfo*)orig;
}
#endif
#endif /* CURLRES_ASYNCH */
#endif /* CURLRES_ARES */
#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,
int curl_dogetaddrinfo(const char *hostname, const char *service,
struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source)
@ -143,12 +138,22 @@ int curl_dogetaddrinfo(char *hostname, char *service,
return res;
}
int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags,
/*
* For CURLRES_ARS, this should be written using ares_gethostbyaddr()
* (ignoring the fact c-ares doesn't return 'serv').
*/
#ifdef HAVE_GETNAMEINFO
int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
GETNAMEINFO_TYPE_ARG2 salen,
char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
GETNAMEINFO_TYPE_ARG7 flags,
int line, const char *source)
{
int res=(getnameinfo)(sa, salen, host, hostlen, serv, servlen, flags);
int res = (getnameinfo)(sa, salen,
host, hostlen,
serv, servlen,
flags);
if(0 == res) {
/* success */
if(logfile)
@ -162,6 +167,7 @@ int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen,
}
return res;
}
#endif
void curl_dofreeaddrinfo(struct addrinfo *freethis,
int line, const char *source)
@ -171,8 +177,7 @@ void curl_dofreeaddrinfo(struct addrinfo *freethis,
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
source, line, (void *)freethis);
}
#endif
#endif /* CURLDEBUG */
/*
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
@ -191,9 +196,30 @@ bool Curl_ipvalid(struct SessionHandle *data)
return TRUE;
}
#ifndef USE_THREADING_GETADDRINFO
#if !defined(USE_THREADING_GETADDRINFO) && !defined(CURLRES_ARES)
#ifdef DEBUG_ADDRINFO
static void dump_addrinfo(struct connectdata *conn, const struct addrinfo *ai)
{
printf("dump_addrinfo:\n");
for ( ; ai; ai = ai->ai_next) {
char buf[INET6_ADDRSTRLEN];
printf(" fam %2d, CNAME %s, ",
ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
if (Curl_printable_address(ai, buf, sizeof(buf)))
printf("%s\n", buf);
else
printf("failed; %s\n", Curl_strerror(conn, Curl_sockerrno()));
}
}
#else
#define dump_addrinfo(x,y)
#endif
/*
* Curl_getaddrinfo() when built ipv6-enabled (non-threading version).
* Curl_getaddrinfo() when built ipv6-enabled (non-threading and
* non-ares version).
*
* Returns name information about the given hostname and port number. If
* successful, the 'addrinfo' is returned and the forth argument will point to
@ -201,13 +227,15 @@ bool Curl_ipvalid(struct SessionHandle *data)
* Curl_freeaddrinfo(), nothing else.
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
const char *hostname,
int port,
int *waitp)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
char *sbufptr = NULL;
char addrbuf[128];
curl_socket_t s;
int pf;
struct SessionHandle *data = conn->data;
@ -216,7 +244,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
/* see if we have an IPv6 stack */
s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s < 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. */
@ -244,20 +272,35 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
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);
hints.ai_socktype = conn->socktype;
if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
(1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {
/* the given address is numerical only, prevent a reverse lookup */
hints.ai_flags = AI_NUMERICHOST;
}
#if 0 /* removed nov 8 2005 before 7.15.1 */
else
hints.ai_flags = AI_CANONNAME;
#endif
if(port) {
snprintf(sbuf, sizeof(sbuf), "%d", port);
sbufptr=sbuf;
}
error = getaddrinfo(hostname, sbufptr, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
return NULL;
}
dump_addrinfo(conn, res);
return res;
}
#endif /* USE_THREADING_GETADDRINFO */
#endif /* !USE_THREADING_GETADDRINFO && !CURLRES_ARES */
#endif /* ipv6 */

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -24,13 +24,10 @@
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef NEED_MALLOC_H
#include <malloc.h>
#else
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -57,21 +54,15 @@
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#ifdef HAVE_PROCESS_H
#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"
@ -87,7 +78,7 @@
#include "inet_ntoa_r.h"
#endif
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -133,17 +124,15 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
* 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)
int Curl_resolv_getsock(struct connectdata *conn,
curl_socket_t *sock,
int numsocks)
{
(void)conn;
(void)read_fd_set;
(void)write_fd_set;
(void)max_fdp;
(void)sock;
(void)numsocks;
return CURLE_OK;
return 0; /* no bits since we don't use any socks */
}
#endif /* truly sync */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -26,11 +26,9 @@
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#ifdef NEED_MALLOC_H
#include <malloc.h>
#else
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -57,13 +55,12 @@
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
@ -79,16 +76,21 @@
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "multiif.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "inet_ntop.h"
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#if defined(_MSC_VER) && defined(CURL_NO__BEGINTHREADEX)
#pragma message ("No _beginthreadex() available in this RTL")
#endif
/***********************************************************************
* Only for Windows threaded name resolves builds
**********************************************************************/
@ -154,13 +156,126 @@ struct thread_data {
HANDLE thread_hnd;
unsigned thread_id;
DWORD thread_status;
curl_socket_t dummy_sock; /* dummy for Curl_fdset() */
FILE *stderr_file;
curl_socket_t dummy_sock; /* dummy for Curl_resolv_fdset() */
HANDLE mutex_waiting; /* marks that we are still waiting for a resolve */
HANDLE event_resolved; /* marks that the thread obtained the information */
HANDLE event_thread_started; /* marks that the thread has initialized and
started */
HANDLE mutex_terminate; /* serializes access to flag_terminate */
HANDLE event_terminate; /* flag for thread to terminate instead of calling
callbacks */
#ifdef CURLRES_IPV6
struct addrinfo hints;
#endif
};
/* Data for synchronization between resolver thread and its parent */
struct thread_sync_data {
HANDLE mutex_waiting; /* thread_data.mutex_waiting duplicate */
HANDLE mutex_terminate; /* thread_data.mutex_terminate duplicate */
HANDLE event_terminate; /* thread_data.event_terminate duplicate */
char * hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
};
/* Destroy resolver thread synchronization data */
static
void destroy_thread_sync_data(struct thread_sync_data * tsd)
{
if (tsd->hostname) {
free(tsd->hostname);
tsd->hostname = NULL;
}
if (tsd->event_terminate) {
CloseHandle(tsd->event_terminate);
tsd->event_terminate = NULL;
}
if (tsd->mutex_terminate) {
CloseHandle(tsd->mutex_terminate);
tsd->mutex_terminate = NULL;
}
if (tsd->mutex_waiting) {
CloseHandle(tsd->mutex_waiting);
tsd->mutex_waiting = NULL;
}
}
/* Initialize resolver thread synchronization data */
static
BOOL init_thread_sync_data(struct thread_data * td,
char * hostname,
struct thread_sync_data * tsd)
{
HANDLE curr_proc = GetCurrentProcess();
memset(tsd, 0, sizeof(*tsd));
if (!DuplicateHandle(curr_proc, td->mutex_waiting,
curr_proc, &tsd->mutex_waiting, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
/* failed to duplicate the mutex, no point in continuing */
destroy_thread_sync_data(tsd);
return FALSE;
}
if (!DuplicateHandle(curr_proc, td->mutex_terminate,
curr_proc, &tsd->mutex_terminate, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
/* failed to duplicate the mutex, no point in continuing */
destroy_thread_sync_data(tsd);
return FALSE;
}
if (!DuplicateHandle(curr_proc, td->event_terminate,
curr_proc, &tsd->event_terminate, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
/* failed to duplicate the event, no point in continuing */
destroy_thread_sync_data(tsd);
return FALSE;
}
/* Copying hostname string because original can be destroyed by parent
* thread during gethostbyname execution.
*/
tsd->hostname = strdup(hostname);
if (!tsd->hostname) {
/* Memory allocation failed */
destroy_thread_sync_data(tsd);
return FALSE;
}
return TRUE;
}
/* acquire resolver thread synchronization */
static
BOOL acquire_thread_sync(struct thread_sync_data * tsd)
{
/* is the thread initiator still waiting for us ? */
if (WaitForSingleObject(tsd->mutex_waiting, 0) == WAIT_TIMEOUT) {
/* yes, it is */
/* Waiting access to event_terminate */
if (WaitForSingleObject(tsd->mutex_terminate, INFINITE) != WAIT_OBJECT_0) {
/* Something went wrong - now just ignoring */
}
else {
if (WaitForSingleObject(tsd->event_terminate, 0) != WAIT_TIMEOUT) {
/* Parent thread signaled us to terminate.
* This means that all data in conn->async is now destroyed
* and we cannot use it.
*/
}
else {
return TRUE;
}
}
}
return FALSE;
}
/* release resolver thread synchronization */
static
void release_thread_sync(struct thread_sync_data * tsd)
{
ReleaseMutex(tsd->mutex_terminate);
}
#if defined(CURLRES_IPV4)
/*
* gethostbyname_thread() resolves a name, calls the Curl_addrinfo4_callback
@ -174,26 +289,45 @@ 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;
int rc = 0;
/* 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).
/* Duplicate the passed mutex and event handles.
* This allows us to use it even after the container gets destroyed
* due to a resolver timeout.
*/
*stderr = *td->stderr_file;
struct thread_sync_data tsd = { 0,0,0,NULL };
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
/* thread synchronization data initialization failed */
return (unsigned)-1;
}
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;
/* Signaling that we have initialized all copies of data and handles we
need */
SetEvent(td->event_thread_started);
he = gethostbyname (tsd.hostname);
/* is parent thread waiting for us and are we able to access conn members? */
if (acquire_thread_sync(&tsd)) {
/* Mark that we have obtained the information, and that we are calling
* back with it. */
SetEvent(td->event_resolved);
if (he) {
rc = Curl_addrinfo4_callback(conn, CURL_ASYNC_SUCCESS, he);
}
else {
rc = Curl_addrinfo4_callback(conn, (int)WSAGetLastError(), NULL);
}
TRACE(("Winsock-error %d, addr %s\n", conn->async.status,
he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown"));
release_thread_sync(&tsd);
}
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"));
/* clean up */
destroy_thread_sync_data(&tsd);
return (rc);
/* An implicit _endthreadex() here */
}
@ -214,44 +348,99 @@ static unsigned __stdcall getaddrinfo_thread (void *arg)
struct addrinfo *res;
char service [NI_MAXSERV];
int rc;
struct addrinfo hints = td->hints;
*stderr = *td->stderr_file;
/* Duplicate the passed mutex handle.
* This allows us to use it even after the container gets destroyed
* due to a resolver timeout.
*/
struct thread_sync_data tsd = { 0,0,0,NULL };
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
/* thread synchronization data initialization failed */
return -1;
}
itoa(conn->async.port, service, 10);
WSASetLastError(conn->async.status = NO_DATA); /* pending status */
rc = getaddrinfo(conn->async.hostname, service, &td->hints, &res);
/* Signaling that we have initialized all copies of data and handles we
need */
SetEvent(td->event_thread_started);
if (rc == 0) {
rc = getaddrinfo(tsd.hostname, service, &hints, &res);
/* is parent thread waiting for us and are we able to access conn members? */
if (acquire_thread_sync(&tsd)) {
/* Mark that we have obtained the information, and that we are calling
back with it. */
SetEvent(td->event_resolved);
if (rc == 0) {
#ifdef DEBUG_THREADING_GETADDRINFO
dump_addrinfo (conn, res);
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));
rc = Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
}
else {
rc = Curl_addrinfo6_callback(conn, (int)WSAGetLastError(), NULL);
TRACE(("Winsock-error %d, no address\n", conn->async.status));
}
release_thread_sync(&tsd);
}
/* clean up */
destroy_thread_sync_data(&tsd);
return (rc);
/* An implicit _endthreadex() here */
}
#endif
/*
* destroy_thread_data() cleans up async resolver data.
* Curl_destroy_thread_data() cleans up async resolver data and thread handle.
* Complementary of ares_destroy.
*/
static void destroy_thread_data (struct Curl_async *async)
void Curl_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;
struct thread_data *td = (struct thread_data*) async->os_specific;
curl_socket_t sock = td->dummy_sock;
if (td->mutex_terminate && td->event_terminate) {
/* Signaling resolver thread to terminate */
if (WaitForSingleObject(td->mutex_terminate, INFINITE) == WAIT_OBJECT_0) {
SetEvent(td->event_terminate);
ReleaseMutex(td->mutex_terminate);
}
else {
/* Something went wrong - just ignoring it */
}
}
if (td->mutex_terminate)
CloseHandle(td->mutex_terminate);
if (td->event_terminate)
CloseHandle(td->event_terminate);
if (td->event_thread_started)
CloseHandle(td->event_thread_started);
if (sock != CURL_SOCKET_BAD)
sclose(sock);
/* destroy the synchronization objects */
if (td->mutex_waiting)
CloseHandle(td->mutex_waiting);
td->mutex_waiting = NULL;
if (td->event_resolved)
CloseHandle(td->event_resolved);
if (td->thread_hnd)
CloseHandle(td->thread_hnd);
free(async->os_specific);
}
async->hostname = NULL;
@ -269,6 +458,7 @@ static bool init_resolve_thread (struct connectdata *conn,
const Curl_addrinfo *hints)
{
struct thread_data *td = calloc(sizeof(*td), 1);
HANDLE thread_and_event[2] = {0};
if (!td) {
SetLastError(ENOMEM);
@ -288,11 +478,62 @@ static bool init_resolve_thread (struct connectdata *conn,
conn->async.status = 0;
conn->async.dns = NULL;
conn->async.os_specific = (void*) td;
td->dummy_sock = CURL_SOCKET_BAD;
td->stderr_file = stderr;
/* Create the mutex used to inform the resolver thread that we're
* still waiting, and take initial ownership.
*/
td->mutex_waiting = CreateMutex(NULL, TRUE, NULL);
if (td->mutex_waiting == NULL) {
Curl_destroy_thread_data(&conn->async);
SetLastError(EAGAIN);
return FALSE;
}
/* Create the event that the thread uses to inform us that it's
* done resolving. Do not signal it.
*/
td->event_resolved = CreateEvent(NULL, TRUE, FALSE, NULL);
if (td->event_resolved == NULL) {
Curl_destroy_thread_data(&conn->async);
SetLastError(EAGAIN);
return FALSE;
}
/* Create the mutex used to serialize access to event_terminated
* between us and resolver thread.
*/
td->mutex_terminate = CreateMutex(NULL, FALSE, NULL);
if (td->mutex_terminate == NULL) {
Curl_destroy_thread_data(&conn->async);
SetLastError(EAGAIN);
return FALSE;
}
/* Create the event used to signal thread that it should terminate.
*/
td->event_terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
if (td->event_terminate == NULL) {
Curl_destroy_thread_data(&conn->async);
SetLastError(EAGAIN);
return FALSE;
}
/* Create the event used by thread to inform it has initialized its own data.
*/
td->event_thread_started = CreateEvent(NULL, TRUE, FALSE, NULL);
if (td->event_thread_started == NULL) {
Curl_destroy_thread_data(&conn->async);
SetLastError(EAGAIN);
return FALSE;
}
#ifdef _WIN32_WCE
td->thread_hnd = (HANDLE) CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) THREAD_FUNC,
conn, 0, &td->thread_id);
#else
td->thread_hnd = (HANDLE) _beginthreadex(NULL, 0, THREAD_FUNC,
conn, 0, &td->thread_id);
#endif
#ifdef CURLRES_IPV6
curlassert(hints);
td->hints = *hints;
@ -301,14 +542,30 @@ static bool init_resolve_thread (struct connectdata *conn,
#endif
if (!td->thread_hnd) {
#ifdef _WIN32_WCE
TRACE(("CreateThread() failed; %s\n", Curl_strerror(conn,GetLastError())));
#else
SetLastError(errno);
TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn,errno)));
destroy_thread_data(&conn->async);
#endif
Curl_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().
/* Waiting until the thread will initialize its data or it will exit due errors.
*/
thread_and_event[0] = td->thread_hnd;
thread_and_event[1] = td->event_thread_started;
if (WaitForMultipleObjects(sizeof(thread_and_event) /
sizeof(thread_and_event[0]),
(const HANDLE*)thread_and_event, FALSE,
INFINITE) == WAIT_FAILED) {
/* The resolver thread has been created,
* most probably it works now - ignoring this "minor" error
*/
}
/* This socket is only to keep Curl_resolv_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;
@ -341,28 +598,49 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
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));
/* wait for the thread to resolve the name */
status = WaitForSingleObject(td->event_resolved, 1000UL*timeout);
/* mark that we are now done waiting */
ReleaseMutex(td->mutex_waiting);
/* close our handle to the mutex, no point in hanging on to it */
CloseHandle(td->mutex_waiting);
td->mutex_waiting = NULL;
/* close the event handle, it's useless now */
CloseHandle(td->event_resolved);
td->event_resolved = NULL;
/* has the resolver thread succeeded in resolving our query ? */
if (status == WAIT_OBJECT_0) {
/* wait for the thread to exit, it's in the callback sequence */
if (WaitForSingleObject(td->thread_hnd, 5000) == WAIT_TIMEOUT) {
TerminateThread(td->thread_hnd, 0);
conn->async.done = TRUE;
td->thread_status = (DWORD)-1;
TRACE(("%s() thread stuck?!, ", THREAD_NAME));
}
else {
/* 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));
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;
@ -370,25 +648,34 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
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;
if (td->thread_status == CURLE_OUT_OF_MEMORY) {
rc = CURLE_OUT_OF_MEMORY;
failf(data, "Could not resolve host: %s", curl_easy_strerror(rc));
}
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;
if(conn->bits.httpproxy) {
failf(data, "Could not resolve proxy: %s; %s",
conn->proxy.dispname, Curl_strerror(conn, conn->async.status));
rc = CURLE_COULDNT_RESOLVE_PROXY;
}
else {
failf(data, "Could not resolve host: %s; %s",
conn->host.name, Curl_strerror(conn, conn->async.status));
rc = CURLE_COULDNT_RESOLVE_HOST;
}
}
else 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
rc = CURLE_OPERATION_TIMEDOUT;
}
destroy_thread_data(&conn->async);
Curl_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);
if(!conn->async.dns)
conn->bits.close = TRUE;
return (rc);
}
@ -405,7 +692,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
if (conn->async.done) {
/* we're done */
destroy_thread_data(&conn->async);
Curl_destroy_thread_data(&conn->async);
if (!conn->async.dns) {
TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n"));
return CURLE_COULDNT_RESOLVE_HOST;
@ -413,25 +700,25 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
*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)
int Curl_resolv_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
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;
if(numsocks) {
/* return one socket waiting for writable, even though this is just
a dummy */
socks[0] = td->dummy_sock;
return GETSOCK_WRITESOCK(0);
}
}
(void) read_fd_set;
return CURLE_OK;
return 0;
}
#ifdef CURLRES_IPV4
@ -439,11 +726,11 @@ CURLcode Curl_fdset(struct connectdata *conn,
* Curl_getaddrinfo() - for Windows threading without ENABLE_IPV6.
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
const char *hostname,
int port,
int *waitp)
{
struct hostent *h;
struct hostent *h = NULL;
struct SessionHandle *data = conn->data;
in_addr_t in;
@ -461,8 +748,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
}
/* fall-back to blocking version */
infof(data, "init_resolve_thread() failed for %s; code %lu\n",
hostname, GetLastError());
infof(data, "init_resolve_thread() failed for %s; %s\n",
hostname, Curl_strerror(conn,GetLastError()));
h = gethostbyname(hostname);
if (!h) {
@ -479,7 +766,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
* Curl_getaddrinfo() - for Windows threading IPv6 enabled
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
const char *hostname,
int port,
int *waitp)
{
@ -525,8 +812,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
hints.ai_socktype = SOCK_STREAM;
hints.ai_socktype = conn->socktype;
#if 0 /* removed nov 8 2005 before 7.15.1 */
hints.ai_flags = AI_CANONNAME;
#endif
itoa(port, sbuf, 10);
/* fire up a new resolver thread! */
@ -536,8 +825,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
}
/* fall-back to blocking version */
infof(data, "init_resolve_thread() failed for %s; code %lu\n",
hostname, GetLastError());
infof(data, "init_resolve_thread() failed for %s; %s\n",
hostname, Curl_strerror(conn,GetLastError()));
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -29,14 +29,18 @@ bool Curl_compareheader(char *headerline, /* line to check */
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);
CURLcode Curl_proxyCONNECT(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);
CURLcode Curl_http(struct connectdata *conn, bool *done);
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
int Curl_https_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn);
@ -57,5 +61,25 @@ int Curl_http_should_fail(struct connectdata *conn);
public curl/curl.h header. */
#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */
/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST
data get included in the initial data chunk sent to the server. If the
data is larger than this, it will automatically get split up in multiple
system calls.
This value used to be fairly big (100K), but we must take into account that
if the server rejects the POST due for authentication reasons, this data
will always be uncondtionally sent and thus it may not be larger than can
always be afforded to send twice.
It must not be greater than 64K to work on VMS.
*/
#ifndef MAX_INITIAL_POST_SIZE
#define MAX_INITIAL_POST_SIZE (64*1024)
#endif
#ifndef TINY_INITIAL_POST_SIZE
#define TINY_INITIAL_POST_SIZE 1024
#endif
#endif
#endif

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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.
@ -35,7 +35,8 @@
#include "content_encoding.h"
#include "http.h"
#include "curl_memory.h"
#include "memory.h"
#include "easyif.h" /* for Curl_convert_to_network prototype */
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -43,7 +44,7 @@
/* The last #include file should be: */
#include "memdebug.h"
/*
/*
* Chunk format (simplified):
*
* <HEX SIZE>[ chunk extension ] CRLF
@ -83,7 +84,7 @@
void Curl_httpchunk_init(struct connectdata *conn)
{
struct Curl_chunker *chunk = &conn->proto.http->chunk;
struct Curl_chunker *chunk = &conn->data->reqdata.proto.http->chunk;
chunk->hexindex=0; /* start at 0 */
chunk->dataleft=0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */
@ -96,6 +97,9 @@ void Curl_httpchunk_init(struct connectdata *conn)
* client (for byte-counting and whatever).
*
* The states and the state-machine is further explained in the header file.
*
* This function always uses ASCII hex values to accommodate non-ASCII hosts.
* For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
*/
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
char *datap,
@ -103,8 +107,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
ssize_t *wrotep)
{
CURLcode result=CURLE_OK;
struct Curl_chunker *ch = &conn->proto.http->chunk;
struct Curl_transfer_keeper *k = &conn->keep;
struct SessionHandle *data = conn->data;
struct Curl_chunker *ch = &data->reqdata.proto.http->chunk;
struct Curl_transfer_keeper *k = &data->reqdata.keep;
size_t piece;
size_t length = (size_t)datalen;
size_t *wrote = (size_t *)wrotep;
@ -114,7 +119,11 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
if(isxdigit((int)*datap)) {
/* Check for an ASCII hex digit.
We avoid the use of isxdigit to accommodate non-ASCII hosts. */
if((*datap >= 0x30 && *datap <= 0x39) /* 0-9 */
|| (*datap >= 0x41 && *datap <= 0x46) /* A-F */
|| (*datap >= 0x61 && *datap <= 0x66)) { /* a-f */
if(ch->hexindex < MAXNUM_SIZE) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
@ -133,6 +142,17 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
}
/* length and datap are unmodified */
ch->hexbuffer[ch->hexindex]=0;
#ifdef CURL_DOES_CONVERSIONS
/* convert to host encoding before calling strtoul */
result = Curl_convert_from_network(conn->data,
ch->hexbuffer,
ch->hexindex);
if(result != CURLE_OK) {
/* Curl_convert_from_network calls failf if unsuccessful */
/* Treat it as a bad hex character */
return(CHUNKE_ILLEGAL_HEX);
}
#endif /* CURL_DOES_CONVERSIONS */
ch->datasize=strtoul(ch->hexbuffer, NULL, 16);
ch->state = CHUNK_POSTHEX;
}
@ -142,7 +162,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* 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')
if(*datap == 0x0d)
ch->state = CHUNK_CR;
length--;
datap++;
@ -150,13 +170,20 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
case CHUNK_CR:
/* waiting for the LF */
if(*datap == '\n') {
if(*datap == 0x0a) {
/* 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;
if (conn->bits.trailerHdrPresent!=TRUE) {
/* No Trailer: header found - revert to original Curl processing */
ch->state = CHUNK_STOP;
if (1 == length) {
/* This is the final byte, return right now */
return CHUNKE_STOP;
}
}
else {
ch->state = CHUNK_TRAILER; /* attempt to read trailers */
conn->trlPos=0;
}
}
else
@ -179,26 +206,26 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* Write the data portion available */
#ifdef HAVE_LIBZ
switch (conn->keep.content_encoding) {
switch (data->reqdata.keep.content_encoding) {
case IDENTITY:
#endif
if(!k->ignorebody)
result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap,
result = Curl_client_write(conn, 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,
case DEFLATE:
/* update data->reqdata.keep.str to point to the chunk data. */
data->reqdata.keep.str = datap;
result = Curl_unencode_deflate_write(conn, &data->reqdata.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,
/* update data->reqdata.keep.str to point to the chunk data. */
data->reqdata.keep.str = datap;
result = Curl_unencode_gzip_write(conn, &data->reqdata.keep,
(ssize_t)piece);
break;
@ -227,7 +254,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
break;
case CHUNK_POSTCR:
if(*datap == '\r') {
if(*datap == 0x0d) {
ch->state = CHUNK_POSTLF;
datap++;
length--;
@ -237,7 +264,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
break;
case CHUNK_POSTLF:
if(*datap == '\n') {
if(*datap == 0x0a) {
/*
* The last one before we go back to hex state and start all
* over.
@ -250,6 +277,75 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
return CHUNKE_BAD_CHUNK;
break;
case CHUNK_TRAILER:
/* conn->trailer is assumed to be freed in url.c on a
connection basis */
if (conn->trlPos >= conn->trlMax) {
char *ptr;
if(conn->trlMax) {
conn->trlMax *= 2;
ptr = (char*)realloc(conn->trailer,conn->trlMax);
}
else {
conn->trlMax=128;
ptr = (char*)malloc(conn->trlMax);
}
if(!ptr)
return CHUNKE_OUT_OF_MEMORY;
conn->trailer = ptr;
}
conn->trailer[conn->trlPos++]=*datap;
if(*datap == 0x0d)
ch->state = CHUNK_TRAILER_CR;
else {
datap++;
length--;
}
break;
case CHUNK_TRAILER_CR:
if(*datap == 0x0d) {
ch->state = CHUNK_TRAILER_POSTCR;
datap++;
length--;
}
else
return CHUNKE_BAD_CHUNK;
break;
case CHUNK_TRAILER_POSTCR:
if (*datap == 0x0a) {
conn->trailer[conn->trlPos++]=0x0a;
conn->trailer[conn->trlPos]=0;
if (conn->trlPos==2) {
ch->state = CHUNK_STOP;
return CHUNKE_STOP;
}
else {
#ifdef CURL_DOES_CONVERSIONS
/* Convert to host encoding before calling Curl_client_write */
result = Curl_convert_from_network(conn->data,
conn->trailer,
conn->trlPos);
if(result != CURLE_OK) {
/* Curl_convert_from_network calls failf if unsuccessful */
/* Treat it as a bad chunk */
return(CHUNKE_BAD_CHUNK);
}
#endif /* CURL_DOES_CONVERSIONS */
Curl_client_write(conn, CLIENTWRITE_HEADER,
conn->trailer, conn->trlPos);
}
ch->state = CHUNK_TRAILER;
conn->trlPos=0;
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 */

View File

@ -1,18 +1,18 @@
#ifndef __HTTP_CHUNKS_H
#define __HTTP_CHUNKS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -52,8 +52,8 @@ typedef enum {
/* 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 */
/* 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.
@ -62,7 +62,22 @@ typedef enum {
buffer! */
CHUNK_STOP,
/* At this point optional trailer headers can be found, unless the next line
is CRLF */
CHUNK_TRAILER,
/* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR.
Next char must be a LF */
CHUNK_TRAILER_CR,
/* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be
signalled If this is an empty trailer CHUNKE_STOP will be signalled.
Otherwise the trailer will be broadcasted via Curl_client_write() and the
next state will be CHUNK_TRAILER */
CHUNK_TRAILER_POSTCR,
CHUNK_LAST /* never use */
} ChunkyState;
typedef enum {
@ -74,6 +89,7 @@ typedef enum {
CHUNKE_WRITE_ERROR,
CHUNKE_STATE_ERROR,
CHUNKE_BAD_ENCODING,
CHUNKE_OUT_OF_MEMORY,
CHUNKE_LAST
} CHUNKcode;

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -22,7 +22,7 @@
***************************************************************************/
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@ -38,7 +38,8 @@
#include "http_digest.h"
#include "strtok.h"
#include "url.h" /* for Curl_safefree() */
#include "curl_memory.h"
#include "memory.h"
#include "easyif.h" /* included for Curl_convert_... prototypes */
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -59,8 +60,8 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
header */
{
bool more = TRUE;
char *token;
char *tmp;
char *token = NULL;
char *tmp = NULL;
bool foundAuth = FALSE;
bool foundAuthInt = FALSE;
struct SessionHandle *data=conn->data;
@ -75,7 +76,7 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
}
/* skip initial whitespaces */
while(*header && isspace((int)*header))
while(*header && ISSPACE(*header))
header++;
if(checkprefix("Digest", header)) {
@ -91,9 +92,9 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
while(more) {
char value[32];
char content[128];
size_t totlen;
size_t totlen=0;
while(*header && isspace((int)*header))
while(*header && ISSPACE(*header))
header++;
/* how big can these strings be? */
@ -224,7 +225,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
unsigned char ha2[33];/* 32 digits and 1 zero byte */
char cnoncebuf[7];
char *cnonce;
char *tmp;
char *tmp = NULL;
struct timeval now;
char **allocuserpwd;
@ -234,6 +235,21 @@ CURLcode Curl_output_digest(struct connectdata *conn,
struct SessionHandle *data = conn->data;
struct digestdata *d;
#ifdef CURL_DOES_CONVERSIONS
CURLcode rc;
/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
It converts digest text to ASCII so the MD5 will be correct for
what ultimately goes over the network.
*/
#define CURL_OUTPUT_DIGEST_CONV(a, b) \
rc = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
if (rc != CURLE_OK) { \
free(b); \
return rc; \
}
#else
#define CURL_OUTPUT_DIGEST_CONV(a, b)
#endif /* CURL_DOES_CONVERSIONS */
if(proxy) {
d = &data->state.proxydigest;
@ -270,7 +286,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
/* Generate a cnonce */
now = Curl_tvnow();
snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", now.tv_sec);
if(Curl_base64_encode(cnoncebuf, strlen(cnoncebuf), &cnonce))
if(Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce))
d->cnonce = cnonce;
else
return CURLE_OUT_OF_MEMORY;
@ -291,6 +307,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
aprintf("%s:%s:%s", userp, d->realm, passwdp);
if(!md5this)
return CURLE_OUT_OF_MEMORY;
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
@ -303,10 +321,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
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;
CURL_OUTPUT_DIGEST_CONV(data, tmp); /* convert on non-ASCII machines */
Curl_md5it(md5buf, (unsigned char *)tmp);
free(tmp); /* free this again */
md5_to_ascii(md5buf, ha1);
}
/*
@ -333,6 +353,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
entity-body here */
/* TODO: Append H(entity-body)*/
}
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, ha2);
@ -356,6 +377,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
if(!md5this)
return CURLE_OUT_OF_MEMORY;
CURL_OUTPUT_DIGEST_CONV(data, md5this); /* convert on non-ASCII machines */
Curl_md5it(md5buf, md5this);
free(md5this); /* free this again */
md5_to_ascii(md5buf, request_digest);

View File

@ -1,18 +1,18 @@
#ifndef __HTTP_DIGEST_H
#define __HTTP_DIGEST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -47,7 +47,12 @@ 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);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
void Curl_digest_cleanup(struct SessionHandle *data);
#else
#define Curl_digest_cleanup(x) do {} while(0)
#endif
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -34,14 +34,13 @@
#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"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -111,7 +110,7 @@ log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix)
gss_release_buffer(&min_stat, &status_string);
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
infof(conn->data, buf);
infof(conn->data, "%s", buf);
}
int Curl_input_negotiate(struct connectdata *conn, char *header)
@ -125,7 +124,7 @@ int Curl_input_negotiate(struct connectdata *conn, char *header)
bool gss;
const char* protocol;
while(*header && isspace((int)*header))
while(*header && ISSPACE(*header))
header++;
if(checkprefix("GSS-Negotiate", header)) {
protocol = "GSS-Negotiate";
@ -161,17 +160,12 @@ int Curl_input_negotiate(struct connectdata *conn, char *header)
return ret;
header += strlen(neg_ctx->protocol);
while(*header && isspace((int)*header))
while(*header && ISSPACE(*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);
int rawlen = Curl_base64_decode(header, (unsigned char **)&input_token.value);
if (rawlen < 0)
return -1;
input_token.length = rawlen;
@ -211,7 +205,7 @@ int Curl_input_negotiate(struct connectdata *conn, char *header)
input_token.length = mechTokenLength;
free(mechToken);
mechToken = NULL;
infof(conn->data, "Parse SPNEGO Target Token succeded\n");
infof(conn->data, "Parse SPNEGO Target Token succeeded\n");
}
}
#endif
@ -292,11 +286,12 @@ CURLcode Curl_output_negotiate(struct connectdata *conn)
neg_ctx->output_token.length = spnegoTokenLength;
free(spnegoToken);
spnegoToken = NULL;
infof(conn->data, "Make SPNEGO Initial Token succeded\n");
infof(conn->data, "Make SPNEGO Initial Token succeeded\n");
}
}
#endif
len = Curl_base64_encode(neg_ctx->output_token.value,
len = Curl_base64_encode(conn->data,
neg_ctx->output_token.value,
neg_ctx->output_token.length,
&encoded);

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,18 @@
#ifndef __HTTP_NTLM_H
#define __HTTP_NTLM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -38,7 +38,10 @@ 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);
void Curl_ntlm_cleanup(struct connectdata *conn);
#ifndef USE_NTLM
#define Curl_ntlm_cleanup(x)
#endif
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -31,8 +31,15 @@
#include <unistd.h>
#endif
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN32__) && \
!defined(__riscos__) && !defined(__INTERIX) && !defined(NETWARE)
#include "if2ip.h"
/*
* This test can probably be simplified to #if defined(SIOCGIFADDR) and
* moved after the following includes.
*/
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN__) && \
!defined(__riscos__) && !defined(__INTERIX) && !defined(NETWARE) && \
!defined(_AMIGASF) && !defined(__minix)
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@ -55,7 +62,6 @@
#include <sys/ioctl.h>
#endif
/* -- if2ip() -- */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@ -64,16 +70,12 @@
#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
#ifdef VMS
#include <inet.h>
#endif
#include "if2ip.h"
#include "curl_memory.h"
#include "inet_ntop.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -100,7 +102,7 @@ char *Curl_if2ip(const char *interface, char *buf, int buf_size)
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
#ifdef IOCTL_3_ARGS
if (SYS_ERROR == ioctl(dummy, SIOCGIFADDR, &req)) {
#else
if (SYS_ERROR == ioctl(dummy, SIOCGIFADDR, &req, sizeof(req))) {
@ -111,19 +113,9 @@ char *Curl_if2ip(const char *interface, char *buf, int buf_size)
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
struct sockaddr_in *s = (struct sockaddr_in *)&req.ifr_dstaddr;
memcpy(&in, &s->sin_addr, sizeof(in));
ip = (char *) Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
}
sclose(dummy);
}
@ -132,9 +124,9 @@ char *Curl_if2ip(const char *interface, char *buf, int buf_size)
/* -- end of if2ip() -- */
#else
char *Curl_if2ip(const char *interface, char *buf, int buf_size)
char *Curl_if2ip(const char *interf, char *buf, int buf_size)
{
(void) interface;
(void) interf;
(void) buf;
(void) buf_size;
return NULL;

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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
@ -24,13 +24,11 @@
***************************************************************************/
#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
extern char *Curl_if2ip(const char *interf, char *buf, int buf_size);
#ifdef __INTERIX
#include <sys/socket.h>
/* Nedelcho Stanev's work-around for SFU 3.0 */
struct ifreq {
#define IFNAMSIZ 16

View File

@ -1,5 +1,38 @@
#ifndef __INET_NTOA_R_H
#define __INET_NTOA_R_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, 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_NTOA_R_2_ARGS
/*
* uClibc 0.9.26 (at least) doesn't define this prototype. The buffer
* must be at least 16 characters long.
*/
char *inet_ntoa_r(const struct in_addr in, char buffer[]);
#else
/*
* My solaris 5.6 system running gcc 2.8.1 does *not* have this prototype
* in any system include file! Isn't that weird?
@ -7,3 +40,5 @@
char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen);
#endif
#endif

View File

@ -1,3 +1,19 @@
/*
* Copyright (C) 1996-2001 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.
*/
/*
* Original code by Paul Vixie. "curlified" by Gisle Vanem.
*/
@ -39,7 +55,7 @@
#define INADDRSZ 4
#define INT16SZ 2
#ifdef WIN32
#ifdef USE_WINSOCK
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define SET_ERRNO(e) WSASetLastError(errno = (e))
#else
@ -52,20 +68,21 @@
* Returns `dst' (as a const)
* Note:
* - uses no statics
* - takes a u_char* not an in_addr as input
* - takes a unsigned char* not an in_addr as input
*/
static const char *inet_ntop4 (const u_char *src, char *dst, size_t size)
static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
{
#ifdef HAVE_INET_NTOA_R
#if defined(HAVE_INET_NTOA_R_2_ARGS)
const char *ptr;
curlassert(size >= 16);
ptr = inet_ntoa_r(*(struct in_addr*)src, dst);
return (char *)memmove(dst, ptr, strlen(ptr)+1);
#elif defined(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);
const char *addr = inet_ntoa(*(struct in_addr*)src);
if (strlen(addr) >= size)
{
@ -80,7 +97,7 @@ static const char *inet_ntop4 (const u_char *src, char *dst, size_t size)
/*
* Convert IPv6 binary address into presentation (printable) format.
*/
static const char *inet_ntop6 (const u_char *src, char *dst, size_t size)
static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
@ -89,25 +106,28 @@ static const char *inet_ntop6 (const u_char *src, char *dst, size_t size)
* 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 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;
unsigned 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));
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;
best.len = 0;
cur.len = 0;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
{
if (words[i] == 0)
@ -184,17 +204,17 @@ static const char *inet_ntop6 (const u_char *src, char *dst, size_t size)
/*
* Convert a network format address to presentation format.
*
* Returns pointer to presentation format address (`dst'),
* Returns pointer to presentation format address (`buf'),
* Returns NULL on error (see errno).
*/
const char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
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);
return inet_ntop4((const unsigned char*)src, buf, size);
#ifdef ENABLE_IPV6
case AF_INET6:
return inet_ntop6((const u_char*)src, buf, size);
return inet_ntop6((const unsigned char*)src, buf, size);
#endif
default:
SET_ERRNO(EAFNOSUPPORT);

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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
@ -25,13 +25,13 @@
#include "setup.h"
char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
#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);
#define Curl_inet_ntop(af,addr,buf,size) inet_ntop(af,addr,buf,size)
#endif
#endif /* __INET_NTOP_H */

View File

@ -44,7 +44,7 @@
#define INADDRSZ 4
#define INT16SZ 2
#ifdef WIN32
#ifdef USE_WINSOCK
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#endif
@ -72,21 +72,21 @@ static int inet_pton6(const char *src, unsigned char *dst);
int
Curl_inet_pton(int af, const char *src, void *dst)
{
switch (af) {
case AF_INET:
return (inet_pton4(src, dst));
switch (af) {
case AF_INET:
return (inet_pton4(src, (unsigned char *)dst));
#ifdef ENABLE_IPV6
#ifndef AF_INET6
#define AF_INET6 AF_MAX+1 /* just to let this compile */
#define AF_INET6 (AF_MAX+1) /* just to let this compile */
#endif
case AF_INET6:
return (inet_pton6(src, dst));
case AF_INET6:
return (inet_pton6(src, (unsigned char *)dst));
#endif
default:
errno = EAFNOSUPPORT;
return (-1);
}
/* NOTREACHED */
default:
errno = EAFNOSUPPORT;
return (-1);
}
/* NOTREACHED */
}
/* int
@ -102,40 +102,41 @@ Curl_inet_pton(int af, const char *src, void *dst)
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;
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;
saw_digit = 0;
octets = 0;
tp = tmp;
*tp = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr(digits, ch)) != NULL) {
size_t new = *tp * 10 + (pch - digits);
if ((pch = strchr(digits, ch)) != NULL) {
unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
if (new > 255)
return (0);
*tp = (unsigned char)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);
if (val > 255)
return (0);
*tp = val;
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
@ -155,85 +156,85 @@ inet_pton4(const char *src, unsigned char *dst)
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;
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned 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;
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;
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);
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 */

View File

@ -1,18 +1,18 @@
#ifndef __INET_PTON_H
#define __INET_PTON_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -25,13 +25,18 @@
#include "setup.h"
int Curl_inet_pton(int, const char *, void *);
#ifdef HAVE_INET_PTON
#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
#if defined(HAVE_NO_INET_PTON_PROTO)
int inet_pton(int af, const char *src, void *dst);
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#else
int Curl_inet_pton(int, const char *, void *);
#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
#endif
#endif /* __INET_PTON_H */

View File

@ -1,14 +1,13 @@
/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
* use in Curl. His latest changes were done 2000-09-18.
* use in Curl. Martin's 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.
* It has since been patched away like a madman by Daniel Stenberg to make it
* better applied to curl conditions, and to make it not use globals, pollute
* name space and more.
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* Copyright (c) 2004 - 2007 Daniel Stenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -36,15 +35,16 @@
* 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. */
* SUCH DAMAGE.
*
* $Id$
*/
#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>
@ -57,10 +57,12 @@
#include <unistd.h> /* for getpid() */
#endif
#include "urldata.h"
#include "base64.h"
#include "ftp.h"
#include "sendf.h"
#include "krb4.h"
#include "curl_memory.h"
#include "memory.h"
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
@ -199,7 +201,8 @@ krb4_auth(void *app_data, struct connectdata *conn)
{
int ret;
char *p;
int len;
unsigned char *ptr;
size_t len;
KTEXT_ST adat;
MSG_DAT msg_data;
int checksum;
@ -220,7 +223,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
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));
infof(data, "%s\n", krb_get_err_text(ret));
return AUTH_CONTINUE;
}
@ -232,7 +235,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
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",
infof(data, "Can't get address for realm %s\n",
krb_realmofhost(host));
else {
if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
@ -242,14 +245,14 @@ krb4_auth(void *app_data, struct connectdata *conn)
#else
char *ip = (char *)inet_ntoa(natAddr);
#endif
Curl_infof(data, "Using NAT IP address (%s) for kerberos 4\n", ip);
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) {
if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) {
Curl_failf(data, "Out of memory base64-encoding");
return AUTH_CONTINUE;
}
@ -275,11 +278,17 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_ERROR;
}
p += 5;
len = Curl_base64_decode(p, (char *)adat.dat);
if(len < 0) {
len = Curl_base64_decode(p, &ptr);
if(len > sizeof(adat.dat)-1) {
free(ptr);
len=0;
}
if(!len || !ptr) {
Curl_failf(data, "Failed to decode base64 from server");
return AUTH_ERROR;
}
memcpy((char *)adat.dat, ptr, len);
free(ptr);
adat.length = len;
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
(struct sockaddr_in *)hisctladdr,
@ -317,10 +326,11 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
char *name;
char *p;
char passwd[100];
int tmp;
size_t tmp;
ssize_t nread;
int save;
CURLcode result;
unsigned char *ptr;
save = Curl_set_command_prot(conn, prot_private);
@ -346,12 +356,18 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
}
p += 2;
tmp = Curl_base64_decode(p, (char *)tkt.dat);
if(tmp < 0) {
tmp = Curl_base64_decode(p, &ptr);
if(tmp >= sizeof(tkt.dat)) {
free(ptr);
tmp=0;
}
if(!tmp || !ptr) {
Curl_failf(conn->data, "Failed to decode base64 in reply.\n");
Curl_set_command_prot(conn, save);
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
memcpy((char *)tkt.dat, ptr, tmp);
free(ptr);
tkt.length = tmp;
tktcopy.length = tkt.length;
@ -384,7 +400,8 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
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) {
if(Curl_base64_encode(conn->data, (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;

View File

@ -1,18 +1,18 @@
#ifndef __KRB4_H
#define __KRB4_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -22,6 +22,49 @@
*
* $Id$
***************************************************************************/
struct Curl_sec_client_mech {
const char *name;
size_t size;
int (*init)(void *);
int (*auth)(void *, struct connectdata *);
void (*end)(void *);
int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
int (*encode)(void *, void*, int, int, void**, struct connectdata *);
int (*decode)(void *, void*, int, int, struct connectdata *);
};
#define AUTH_OK 0
#define AUTH_CONTINUE 1
#define AUTH_ERROR 2
extern struct Curl_sec_client_mech Curl_krb4_client_mech;
CURLcode Curl_krb_kauth(struct connectdata *conn);
int Curl_sec_fflush_fd(struct connectdata *conn, int fd);
int Curl_sec_fprintf (struct connectdata *, FILE *, const char *, ...);
int Curl_sec_getc (struct connectdata *conn, FILE *);
int Curl_sec_putc (struct connectdata *conn, int, FILE *);
int Curl_sec_read (struct connectdata *conn, int, void *, int);
int Curl_sec_read_msg (struct connectdata *conn, char *, int);
int Curl_sec_vfprintf(struct connectdata *, FILE *, const char *, va_list);
int Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...);
int Curl_sec_vfprintf2(struct connectdata *conn, FILE *, const char *, va_list);
ssize_t Curl_sec_send(struct connectdata *conn, int, char *, int);
int Curl_sec_write(struct connectdata *conn, int, char *, int);
void Curl_sec_end (struct connectdata *);
int Curl_sec_login (struct connectdata *);
void Curl_sec_prot (int, char **);
int Curl_sec_request_prot (struct connectdata *conn, const char *level);
void Curl_sec_set_protection_level(struct connectdata *conn);
void Curl_sec_status (void);
enum protection_level Curl_set_command_prot(struct connectdata *,
enum protection_level);
#endif

View File

@ -3,9 +3,9 @@
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -30,14 +30,19 @@
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef NEED_MALLOC_H
#include <malloc.h>
#endif
#include <errno.h>
#if defined(WIN32)
# include <windows.h>
# include <malloc.h>
# include <WinLdap.h>
# include <winldap.h>
#endif
#ifdef HAVE_UNISTD_H
@ -56,7 +61,8 @@
#include "strequal.h"
#include "strtok.h"
#include "ldap.h"
#include "curl_memory.h"
#include "memory.h"
#include "base64.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -64,7 +70,8 @@
#include "memdebug.h"
/* WLdap32.dll functions are *not* stdcall. Must call these via __cdecl
* pointers in case libcurl was compiled as fastcall (-Gr).
* pointers in case libcurl was compiled as fastcall (cl -Gr). Watcom
* uses fastcall by default.
*/
#if !defined(WIN32) && !defined(__cdecl)
#define __cdecl
@ -73,8 +80,17 @@
#ifndef LDAP_SIZELIMIT_EXCEEDED
#define LDAP_SIZELIMIT_EXCEEDED 4
#endif
#ifndef LDAP_VERSION2
#define LDAP_VERSION2 2
#endif
#ifndef LDAP_VERSION3
#define LDAP_VERSION3 3
#endif
#ifndef LDAP_OPT_PROTOCOL_VERSION
#define LDAP_OPT_PROTOCOL_VERSION 0x0011
#endif
#define DLOPEN_MODE RTLD_LAZY /*! assume all dlopen() implementations have
#define DLOPEN_MODE RTLD_LAZY /*! assume all dlopen() implementations have
this */
#if defined(RTLD_LAZY_GLOBAL) /* It turns out some systems use this: */
@ -99,43 +115,60 @@
#undef HAVE_LIBDL
#endif
/*
* We use this ZERO_NULL to avoid picky compiler warnings,
* when assigning a NULL pointer to a function pointer var.
*/
#define ZERO_NULL 0
typedef void * (*dynafunc)(void *input);
/***********************************************************************
*/
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL) || defined(WIN32)
static void *libldap = NULL;
#ifndef WIN32
#if defined(DL_LBER_FILE)
static void *liblber = NULL;
#endif
#endif
struct bv {
unsigned long bv_len;
char *bv_val;
};
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
* libldap.so can normally resolve its dependency on liblber.so
* automatically, but in broken installation it does not so
* handle it here by opening liblber.so as global.
*/
*mod_name = "liblber.so";
#ifdef DL_LBER_FILE
*mod_name = DL_LBER_FILE;
liblber = dlopen(*mod_name, DLOPEN_MODE);
if (!liblber)
return 0;
#endif
/* Assume loading libldap.so will fail if loading of liblber.so failed
*/
if (liblber) {
*mod_name = "libldap.so";
libldap = dlopen(*mod_name, RTLD_LAZY);
}
*mod_name = DL_LDAP_FILE;
libldap = dlopen(*mod_name, RTLD_LAZY);
}
return (libldap != NULL && liblber != NULL);
return (libldap != NULL);
#elif defined(WIN32)
*mod_name = "wldap32.dll";
*mod_name = DL_LDAP_FILE;
if (!libldap)
libldap = (void*)LoadLibrary(*mod_name);
return (libldap != NULL);
#else
*mod_name = "";
return (0);
#endif
}
@ -147,10 +180,12 @@ static void DynaClose(void)
dlclose(libldap);
libldap=NULL;
}
#ifdef DL_LBER_FILE
if (liblber) {
dlclose(liblber);
liblber=NULL;
}
#endif
#elif defined(WIN32)
if (libldap) {
FreeLibrary ((HMODULE)libldap);
@ -161,7 +196,7 @@ static void DynaClose(void)
static dynafunc DynaGetFunction(const char *name)
{
dynafunc func = (dynafunc)NULL;
dynafunc func = (dynafunc)ZERO_NULL;
#if defined(HAVE_DLOPEN) || defined(HAVE_LIBDL)
if (libldap) {
@ -175,6 +210,8 @@ static dynafunc DynaGetFunction(const char *name)
if (libldap) {
func = (dynafunc)GetProcAddress((HINSTANCE)libldap, name);
}
#else
(void) name;
#endif
return func;
}
@ -214,7 +251,7 @@ static void (*ldap_free_urldesc)(LDAPURLDesc *) = _ldap_free_urldesc;
#endif
CURLcode Curl_ldap(struct connectdata *conn)
CURLcode Curl_ldap(struct connectdata *conn, bool *done)
{
CURLcode status = CURLE_OK;
int rc = 0;
@ -233,10 +270,11 @@ CURLcode Curl_ldap(struct connectdata *conn)
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_get_values_len)(void *, void *, const char *);
void (__cdecl *ldap_value_free_len)(void **);
void (__cdecl *ldap_memfree)(void *);
void (__cdecl *ber_free)(void *, int);
int (__cdecl *ldap_set_option)(void *, int, void *);
void *server;
LDAPURLDesc *ludp = NULL;
@ -245,7 +283,11 @@ CURLcode Curl_ldap(struct connectdata *conn)
void *entryIterator; /*! type should be 'LDAPMessage *' */
int num = 0;
struct SessionHandle *data=conn->data;
int ldap_proto;
char *val_b64;
size_t val_b64_sz;
*done = TRUE; /* unconditionally */
infof(data, "LDAP local: %s\n", data->change.url);
if (!DynaOpen(&mod_name)) {
@ -256,25 +298,30 @@ CURLcode Curl_ldap(struct connectdata *conn)
/* 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);
DYNA_GET_FUNCTION(void *(__cdecl *)(char *, int), ldap_init);
DYNA_GET_FUNCTION(int (__cdecl *)(void *, char *, char *),
ldap_simple_bind_s);
DYNA_GET_FUNCTION(int (__cdecl *)(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);
DYNA_GET_FUNCTION(int (__cdecl *)(void *, char *, int, char *, char **, int,
void **), ldap_search_s);
DYNA_GET_FUNCTION(void *(__cdecl *)(void *, void *), ldap_first_entry);
DYNA_GET_FUNCTION(void *(__cdecl *)(void *, void *), ldap_next_entry);
DYNA_GET_FUNCTION(char *(__cdecl *)(int), ldap_err2string);
DYNA_GET_FUNCTION(char *(__cdecl *)(void *, void *), ldap_get_dn);
DYNA_GET_FUNCTION(char *(__cdecl *)(void *, void *, void **),
ldap_first_attribute);
DYNA_GET_FUNCTION(char *(__cdecl *)(void *, void *, void *),
ldap_next_attribute);
DYNA_GET_FUNCTION(void **(__cdecl *)(void *, void *, const char *),
ldap_get_values_len);
DYNA_GET_FUNCTION(void (__cdecl *)(void **), ldap_value_free_len);
DYNA_GET_FUNCTION(void (__cdecl *)(void *), ldap_memfree);
DYNA_GET_FUNCTION(void (__cdecl *)(void *, int), ber_free);
DYNA_GET_FUNCTION(int (__cdecl *)(void *, int, void *), ldap_set_option);
server = (*ldap_init)(conn->host.name, (int)conn->port);
if (server == NULL) {
@ -284,9 +331,18 @@ CURLcode Curl_ldap(struct connectdata *conn)
goto quit;
}
ldap_proto = LDAP_VERSION3;
(*ldap_set_option)(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
rc = (*ldap_simple_bind_s)(server,
conn->bits.user_passwd ? conn->user : NULL,
conn->bits.user_passwd ? conn->passwd : NULL);
if (rc != 0) {
ldap_proto = LDAP_VERSION2;
(*ldap_set_option)(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
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;
@ -323,35 +379,51 @@ CURLcode Curl_ldap(struct connectdata *conn)
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);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)dn, 0);
Curl_client_write(conn, 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);
struct bv **vals = (struct bv **)
(*ldap_get_values_len)(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);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *) attribute, 0);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
if ((strlen(attribute) > 7) &&
(strcmp(";binary",
(char *)attribute +
(strlen((char *)attribute) - 7)) == 0)) {
/* Binary attribute, encode to base64. */
val_b64_sz = Curl_base64_encode(conn->data,
vals[i]->bv_val,
vals[i]->bv_len,
&val_b64);
if (val_b64_sz > 0) {
Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
free(val_b64);
}
} else
Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
vals[i]->bv_len);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
}
/* Free memory used to store values */
(*ldap_value_free)(vals);
(*ldap_value_free_len)((void **)vals);
}
Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
(*ldap_memfree)(attribute);
(*ldap_memfree)(dn);
}
(*ldap_memfree)(dn);
if (ber)
(*ber_free)(ber, 0);
}
@ -368,7 +440,8 @@ quit:
DynaClose();
/* no data to transfer */
Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
conn->bits.close = TRUE;
return status;
}
@ -436,36 +509,36 @@ static char **split_str (char *str)
/*
* Unescape the LDAP-URL components
*/
static bool unescape_elements (LDAPURLDesc *ludp)
static bool unescape_elements (void *data, LDAPURLDesc *ludp)
{
int i;
if (ludp->lud_filter) {
ludp->lud_filter = curl_unescape(ludp->lud_filter, 0);
ludp->lud_filter = curl_easy_unescape(data, ludp->lud_filter, 0, NULL);
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);
ludp->lud_attrs[i] = curl_easy_unescape(data, ludp->lud_attrs[i], 0, NULL);
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);
ludp->lud_exts[i] = curl_easy_unescape(data, ludp->lud_exts[i], 0, NULL);
if (!ludp->lud_exts[i])
return (FALSE);
}
if (ludp->lud_dn) {
char *dn = ludp->lud_dn;
char *new_dn = curl_unescape(dn, 0);
char *new_dn = curl_easy_unescape(data, dn, 0, NULL);
free(dn);
ludp->lud_dn = new_dn;
if (!new_dn)
return (FALSE);
ludp->lud_dn = new_dn;
}
return (TRUE);
}
@ -477,8 +550,10 @@ static bool unescape_elements (LDAPURLDesc *ludp)
*
* <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 = "".
* extract the rest from 'conn->data->reqdata.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
*/
@ -487,7 +562,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
char *p, *q;
int i;
if (!conn->path || conn->path[0] != '/' ||
if (!conn->data ||
!conn->data->reqdata.path ||
conn->data->reqdata.path[0] != '/' ||
!checkprefix(conn->protostr, conn->data->change.url))
return LDAP_INVALID_SYNTAX;
@ -497,13 +574,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
/* parse DN (Distinguished Name).
*/
ludp->lud_dn = strdup(conn->path+1);
ludp->lud_dn = strdup(conn->data->reqdata.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));
LDAP_TRACE (("DN '%.*s'\n", p ? (size_t)(p-ludp->lud_dn) :
strlen(ludp->lud_dn), ludp->lud_dn));
if (!p)
goto success;
@ -571,7 +648,7 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
LDAP_TRACE (("exts[%d] '%s'\n", i, ludp->lud_exts[i]));
success:
if (!unescape_elements(ludp))
if (!unescape_elements(conn->data, ludp))
return LDAP_NO_MEMORY;
return LDAP_SUCCESS;
}

View File

@ -2,18 +2,18 @@
#define __LDAP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -24,6 +24,6 @@
* $Id$
***************************************************************************/
#ifndef CURL_DISABLE_LDAP
CURLcode Curl_ldap(struct connectdata *conn);
CURLcode Curl_ldap(struct connectdata *conn, bool *done);
#endif
#endif /* __LDAP_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -27,13 +27,13 @@
#include <stdlib.h>
#include "llist.h"
#include "curl_memory.h"
#include "memory.h"
/* this must be the last include file */
#include "memdebug.h"
void
Curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
{
l->size = 0;
l->dtor = dtor;
@ -41,12 +41,12 @@ Curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
l->tail = NULL;
}
curl_llist *
struct curl_llist *
Curl_llist_alloc(curl_llist_dtor dtor)
{
curl_llist *list;
struct curl_llist *list;
list = (curl_llist *)malloc(sizeof(curl_llist));
list = (struct curl_llist *)malloc(sizeof(struct curl_llist));
if(NULL == list)
return NULL;
@ -59,10 +59,11 @@ Curl_llist_alloc(curl_llist_dtor dtor)
* 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_insert_next(struct curl_llist *list, struct curl_llist_element *e,
const void *p)
{
curl_llist_element *ne =
(curl_llist_element *) malloc(sizeof(curl_llist_element));
struct curl_llist_element *ne =
(struct curl_llist_element *) malloc(sizeof(struct curl_llist_element));
if(!ne)
return 0;
@ -91,7 +92,8 @@ Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
}
int
Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
void *user)
{
if (e == NULL || list->size == 0)
return 1;
@ -119,7 +121,7 @@ Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
}
void
Curl_llist_destroy(curl_llist *list, void *user)
Curl_llist_destroy(struct curl_llist *list, void *user)
{
if(list) {
while (list->size > 0)
@ -128,3 +130,9 @@ Curl_llist_destroy(curl_llist *list, void *user)
free(list);
}
}
size_t
Curl_llist_count(struct curl_llist *list)
{
return list->size;
}

View File

@ -1,18 +1,18 @@
#ifndef __LLIST_H
#define __LLIST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -28,29 +28,33 @@
typedef void (*curl_llist_dtor)(void *, void *);
typedef struct _curl_llist_element {
struct curl_llist_element {
void *ptr;
struct _curl_llist_element *prev;
struct _curl_llist_element *next;
} curl_llist_element;
struct curl_llist_element *prev;
struct curl_llist_element *next;
};
typedef struct _curl_llist {
curl_llist_element *head;
curl_llist_element *tail;
struct curl_llist {
struct curl_llist_element *head;
struct 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 *);
void Curl_llist_init(struct curl_llist *, curl_llist_dtor);
struct curl_llist *Curl_llist_alloc(curl_llist_dtor);
int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
const void *);
int Curl_llist_insert_prev(struct curl_llist *, struct curl_llist_element *,
const void *);
int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
void *);
int Curl_llist_remove_next(struct curl_llist *, struct curl_llist_element *,
void *);
size_t Curl_llist_count(struct curl_llist *);
void Curl_llist_destroy(struct curl_llist *, void *);
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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
@ -23,7 +23,9 @@
#include "setup.h"
#ifndef USE_SSLEAY
#ifndef CURL_DISABLE_CRYPTO_AUTH
#if !defined(USE_SSLEAY) || !defined(USE_OPENSSL)
/* 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! */
@ -65,7 +67,7 @@ struct md5_ctx {
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_Update(struct md5_ctx *, const unsigned char *, unsigned int);
static void MD5_Final(unsigned char [16], struct md5_ctx *);
/* Constants for MD5Transform routine.
@ -88,11 +90,11 @@ static void MD5_Final(unsigned char [16], struct md5_ctx *);
#define S43 15
#define S44 21
static void MD5Transform(UINT4 [4], unsigned char [64]);
static void MD5Transform(UINT4 [4], const unsigned char [64]);
static void Encode(unsigned char *, UINT4 *, unsigned int);
static void Decode(UINT4 *, unsigned char *, unsigned int);
static void Decode(UINT4 *, const unsigned char *, unsigned int);
static unsigned char PADDING[64] = {
static const 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
@ -149,9 +151,9 @@ static void MD5_Init(struct md5_ctx *context)
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 */
static void MD5_Update (struct md5_ctx *context, /* context */
const unsigned char *input, /* input block */
unsigned int inputLen) /* length of input block */
{
unsigned int i, bufindex, partLen;
@ -212,7 +214,7 @@ static void MD5_Final(unsigned char digest[16], /* message digest */
/* MD5 basic transformation. Transforms state based on block. */
static void MD5Transform(UINT4 state[4],
unsigned char block[64])
const unsigned char block[64])
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
@ -320,7 +322,7 @@ static void Encode (unsigned char *output,
a multiple of 4.
*/
static void Decode (UINT4 *output,
unsigned char *input,
const unsigned char *input,
unsigned int len)
{
unsigned int i, j;
@ -339,10 +341,12 @@ static void Decode (UINT4 *output,
#include "md5.h"
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
unsigned char *input)
const unsigned char *input)
{
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, input, (unsigned int)strlen((char *)input));
MD5_Final(outbuffer, &ctx);
}
#endif

View File

@ -24,6 +24,6 @@
***************************************************************************/
void Curl_md5it(unsigned char *output,
unsigned char *input);
const unsigned char *input);
#endif

View File

@ -6,7 +6,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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
@ -42,7 +42,7 @@
#endif
#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
#include "curl_memory.h"
#include "memory.h"
#include "memdebug.h"
struct memdebug {
@ -61,25 +61,29 @@ struct memdebug {
*/
#define logfile curl_debuglogfile
FILE *curl_debuglogfile;
static bool memlimit; /* enable memory limit */
static long memsize; /* set number of mallocs allowed */
FILE *curl_debuglogfile = NULL;
static bool memlimit = FALSE; /* enable memory limit */
static long memsize = 0; /* 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;
if (!logfile) {
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;
if (!memlimit) {
memlimit = TRUE;
memsize = limit;
}
}
/* returns TRUE if this isn't allowed! */
@ -95,6 +99,7 @@ static bool countcheck(const char *func, int line, const char *source)
if(source)
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
errno = ENOMEM;
return TRUE; /* RETURN ERROR! */
}
else
@ -200,7 +205,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
mem=(struct memdebug *)(Curl_crealloc)(mem, size);
if(logfile)
fprintf(logfile, "MEM %s:%d realloc(0x%x, %zd) = %p\n",
fprintf(logfile, "MEM %s:%d realloc(%p, %zd) = %p\n",
source, line, ptr, wantedsize, mem?mem->mem:NULL);
if(mem) {

View File

@ -2,18 +2,18 @@
#ifndef _CURL_MEDEBUG_H
#define _CURL_MEDEBUG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -31,6 +31,8 @@
#include "setup.h"
#include <curl/curl.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -48,24 +50,24 @@
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);
CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source);
CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line, const char *source);
CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line, const char *source);
CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
CURL_EXTERN void curl_memdebug(const char *logname);
CURL_EXTERN 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);
CURL_EXTERN int curl_socket(int domain, int type, int protocol, int line , const char *);
CURL_EXTERN int curl_sclose(int sockfd, int, const char *source);
CURL_EXTERN 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);
CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
const char *source);
CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
#ifndef MEMDEBUG_NODEFINES
@ -83,11 +85,26 @@ int curl_fclose(FILE *file, int line, const char *source);
#define accept(sock,addr,len)\
curl_accept(sock,addr,len,__LINE__,__FILE__)
#if defined(getaddrinfo) && defined(__osf__)
/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define
our macro as for other platforms. Instead, we redefine the new name they
define getaddrinfo to become! */
#define ogetaddrinfo(host,serv,hint,res) \
curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
#else
#undef getaddrinfo
#define getaddrinfo(host,serv,hint,res) \
curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
#endif
#ifdef HAVE_GETNAMEINFO
#undef getnameinfo
#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
curl_dogetnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \
__FILE__)
#endif
#undef freeaddrinfo
#define freeaddrinfo(data) \
curl_dofreeaddrinfo(data,__LINE__,__FILE__)

View File

@ -1,10 +1,10 @@
#ifndef _CURL_MEMORY_H
#define _CURL_MEMORY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
@ -12,7 +12,7 @@
* 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.

View File

@ -38,6 +38,10 @@
#include <ctype.h>
#include <string.h>
#if defined(DJGPP) && (DJGPP_MINOR < 4)
#undef _MPRINTF_REPLACE /* don't use x_was_used() here */
#endif
#include <curl/mprintf.h>
#ifndef SIZEOF_LONG_DOUBLE
@ -55,7 +59,7 @@
#define ENABLE_64BIT
#endif
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -75,6 +79,9 @@
# define BOOL char
#endif
#ifdef _AMIGASF
# undef FORMAT_INT
#endif
/* Lower-case digits. */
static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
@ -164,7 +171,7 @@ int curl_msprintf(char *buffer, const char *format, ...);
static long dprintf_DollarString(char *input, char **end)
{
int number=0;
while(isdigit((int)*input)) {
while(ISDIGIT(*input)) {
number *= 10;
number += *input-'0';
input++;
@ -619,10 +626,10 @@ static int dprintf_formatf(
char alt;
/* Width of a field. */
ssize_t width;
long width;
/* Precision of a field. */
ssize_t prec;
long prec;
/* Decimal integer is negative. */
char is_neg;
@ -759,8 +766,8 @@ static int dprintf_formatf(
*w-- = digits[num % base];
num /= base;
}
width -= workend - w;
prec -= workend - w;
width -= (long)(workend - w);
prec -= (long)(workend - w);
if (alt && base == 8 && prec <= 0) {
*w-- = '0';
@ -816,8 +823,8 @@ static int dprintf_formatf(
case FORMAT_STRING:
/* String. */
{
static char null[] = "(nil)";
char *str;
static const char null[] = "(nil)";
const char *str;
size_t len;
str = (char *) p->data.str;
@ -830,7 +837,7 @@ static int dprintf_formatf(
p->flags &= (~FLAGS_ALT);
}
else {
str = (char *)"";
str = "";
len = 0;
}
}
@ -839,7 +846,7 @@ static int dprintf_formatf(
if (prec != -1 && (size_t) prec < len)
len = prec;
width -= len;
width -= (long)len;
if (p->flags & FLAGS_ALT)
OUTCHAR('"');
@ -869,14 +876,14 @@ static int dprintf_formatf(
base = 16;
digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
alt = 1;
num = (unsigned long) ptr;
num = (size_t) ptr;
is_neg = 0;
goto number;
}
else {
/* Write "(nil)" for a nil pointer. */
static char strnil[] = "(nil)";
char *point;
static const char strnil[] = "(nil)";
const char *point;
width -= sizeof(strnil) - 1;
if (p->flags & FLAGS_LEFT)
@ -933,7 +940,6 @@ static int dprintf_formatf(
fptr += len;
left -= len;
}
(void)left;
if (p->flags & FLAGS_LONG)
*fptr++ = 'l';
@ -1134,15 +1140,12 @@ int curl_msprintf(char *buffer, const char *format, ...)
return retcode;
}
#if !(defined( WIN32) || defined(__UCLIBC__)) /* not needed on win32 */
extern int fputc(int, FILE *);
#endif
int curl_mprintf(const char *format, ...)
{
int retcode;
va_list ap_save; /* argument pointer */
va_start(ap_save, format);
retcode = dprintf_formatf(stdout, fputc, format, ap_save);
va_end(ap_save);
return retcode;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
#ifndef __MULTIIF_H
#define __MULTIIF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, 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$
***************************************************************************/
/*
* Prototypes for library-wide functions provided by multi.c
*/
void Curl_expire(struct SessionHandle *data, long milli);
void Curl_multi_rmeasy(void *multi, CURL *data);
bool Curl_multi_canPipeline(struct Curl_multi* multi);
/* the write bits start at bit 16 for the *getsock() bitmap */
#define GETSOCK_WRITEBITSTART 16
#define GETSOCK_BLANK 0 /* no bits set */
/* set the bit for the given sock number to make the bitmap for writable */
#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x)))
/* set the bit for the given sock number to make the bitmap for readable */
#define GETSOCK_READSOCK(x) (1 << (x))
#endif /* __MULTIIF_H */

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -45,7 +45,7 @@
#include "strequal.h"
#include "strtok.h"
#include "curl_memory.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@ -83,7 +83,7 @@ int Curl_parsenetrc(char *host,
FILE *file;
int retcode=1;
int specific_login = (login[0] != 0);
char *home = NULL;
char *home = NULL;
bool home_alloc = FALSE;
bool netrc_alloc = FALSE;
int state=NOTHING;
@ -103,7 +103,7 @@ int Curl_parsenetrc(char *host,
char *override = curl_getenv("CURL_DEBUG_NETRC");
if (override) {
printf("NETRC: overridden " NETRC " file: %s\n", home);
fprintf(stderr, "NETRC: overridden " NETRC " file: %s\n", override);
netrcfile = override;
netrc_alloc = TRUE;
}
@ -171,7 +171,7 @@ int Curl_parsenetrc(char *host,
/* and yes, this is our host! */
state=HOSTVALID;
#ifdef _NETRC_DEBUG
printf("HOST: %s\n", tok);
fprintf(stderr, "HOST: %s\n", tok);
#endif
retcode=0; /* we did find our host */
}
@ -188,7 +188,7 @@ int Curl_parsenetrc(char *host,
else {
strncpy(login, tok, LOGINSIZE-1);
#ifdef _NETRC_DEBUG
printf("LOGIN: %s\n", login);
fprintf(stderr, "LOGIN: %s\n", login);
#endif
}
state_login=0;
@ -197,7 +197,7 @@ int Curl_parsenetrc(char *host,
if (state_our_login || !specific_login) {
strncpy(password, tok, PASSWORDSIZE-1);
#ifdef _NETRC_DEBUG
printf("PASSWORD: %s\n", password);
fprintf(stderr, "PASSWORD: %s\n", password);
#endif
}
state_password=0;

View File

@ -30,7 +30,7 @@
#include <nks/thread.h>
#include <nks/synch.h>
#include "curl_memory.h"
#include "memory.h"
#include "memdebug.h"
typedef struct

View File

@ -0,0 +1,425 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, 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$
***************************************************************************/
/*
A brief summary of the date string formats this parser groks:
RFC 2616 3.3.1
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
we support dates without week day name:
06 Nov 1994 08:49:37 GMT
06-Nov-94 08:49:37 GMT
Nov 6 08:49:37 1994
without the time zone:
06 Nov 1994 08:49:37
06-Nov-94 08:49:37
weird order:
1994 Nov 6 08:49:37 (GNU date fails)
GMT 08:49:37 06-Nov-94 Sunday
94 6 Nov 08:49:37 (GNU date fails)
time left out:
1994 Nov 6
06-Nov-94
Sun Nov 6 94
unusual separators:
1994.Nov.6
Sun/Nov/6/94/GMT
commonly used time zone names:
Sun, 06 Nov 1994 08:49:37 CET
06 Nov 1994 08:49:37 EST
time zones specified using RFC822 style:
Sun, 12 Sep 2004 15:05:58 -0700
Sat, 11 Sep 2004 21:32:11 +0200
compact numerical date strings:
20040912 15:05:58 -0700
20040911 +0200
*/
#include "setup.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* for strtol() */
#endif
#include <curl/curl.h>
static time_t Curl_parsedate(const char *date);
const char * const Curl_wkday[] =
{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
static const char * const weekday[] =
{ "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday" };
const char * const Curl_month[]=
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
struct tzinfo {
const char *name;
int offset; /* +/- in minutes */
};
/* Here's a bunch of frequently used time zone names. These were supported
by the old getdate parser. */
#define tDAYZONE -60 /* offset for daylight savings time */
static const struct tzinfo tz[]= {
{"GMT", 0}, /* Greenwich Mean */
{"UTC", 0}, /* Universal (Coordinated) */
{"WET", 0}, /* Western European */
{"BST", 0 tDAYZONE}, /* British Summer */
{"WAT", 60}, /* West Africa */
{"AST", 240}, /* Atlantic Standard */
{"ADT", 240 tDAYZONE}, /* Atlantic Daylight */
{"EST", 300}, /* Eastern Standard */
{"EDT", 300 tDAYZONE}, /* Eastern Daylight */
{"CST", 360}, /* Central Standard */
{"CDT", 360 tDAYZONE}, /* Central Daylight */
{"MST", 420}, /* Mountain Standard */
{"MDT", 420 tDAYZONE}, /* Mountain Daylight */
{"PST", 480}, /* Pacific Standard */
{"PDT", 480 tDAYZONE}, /* Pacific Daylight */
{"YST", 540}, /* Yukon Standard */
{"YDT", 540 tDAYZONE}, /* Yukon Daylight */
{"HST", 600}, /* Hawaii Standard */
{"HDT", 600 tDAYZONE}, /* Hawaii Daylight */
{"CAT", 600}, /* Central Alaska */
{"AHST", 600}, /* Alaska-Hawaii Standard */
{"NT", 660}, /* Nome */
{"IDLW", 720}, /* International Date Line West */
{"CET", -60}, /* Central European */
{"MET", -60}, /* Middle European */
{"MEWT", -60}, /* Middle European Winter */
{"MEST", -60 tDAYZONE}, /* Middle European Summer */
{"CEST", -60 tDAYZONE}, /* Central European Summer */
{"MESZ", -60 tDAYZONE}, /* Middle European Summer */
{"FWT", -60}, /* French Winter */
{"FST", -60 tDAYZONE}, /* French Summer */
{"EET", -120}, /* Eastern Europe, USSR Zone 1 */
{"WAST", -420}, /* West Australian Standard */
{"WADT", -420 tDAYZONE}, /* West Australian Daylight */
{"CCT", -480}, /* China Coast, USSR Zone 7 */
{"JST", -540}, /* Japan Standard, USSR Zone 8 */
{"EAST", -600}, /* Eastern Australian Standard */
{"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */
{"GST", -600}, /* Guam Standard, USSR Zone 9 */
{"NZT", -720}, /* New Zealand */
{"NZST", -720}, /* New Zealand Standard */
{"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */
{"IDLE", -720}, /* International Date Line East */
};
/* returns:
-1 no day
0 monday - 6 sunday
*/
static int checkday(char *check, size_t len)
{
int i;
const char * const *what;
bool found= FALSE;
if(len > 3)
what = &weekday[0];
else
what = &Curl_wkday[0];
for(i=0; i<7; i++) {
if(curl_strequal(check, what[0])) {
found=TRUE;
break;
}
what++;
}
return found?i:-1;
}
static int checkmonth(char *check)
{
int i;
const char * const *what;
bool found= FALSE;
what = &Curl_month[0];
for(i=0; i<12; i++) {
if(curl_strequal(check, what[0])) {
found=TRUE;
break;
}
what++;
}
return found?i:-1; /* return the offset or -1, no real offset is -1 */
}
/* return the time zone offset between GMT and the input one, in number
of seconds or -1 if the timezone wasn't found/legal */
static int checktz(char *check)
{
unsigned int i;
const struct tzinfo *what;
bool found= FALSE;
what = tz;
for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
if(curl_strequal(check, what->name)) {
found=TRUE;
break;
}
what++;
}
return found?what->offset*60:-1;
}
static void skip(const char **date)
{
/* skip everything that aren't letters or digits */
while(**date && !ISALNUM(**date))
(*date)++;
}
enum assume {
DATE_MDAY,
DATE_YEAR,
DATE_TIME
};
static time_t Curl_parsedate(const char *date)
{
time_t t = 0;
int wdaynum=-1; /* day of the week number, 0-6 (mon-sun) */
int monnum=-1; /* month of the year number, 0-11 */
int mdaynum=-1; /* day of month, 1 - 31 */
int hournum=-1;
int minnum=-1;
int secnum=-1;
int yearnum=-1;
int tzoff=-1;
struct tm tm;
enum assume dignext = DATE_MDAY;
const char *indate = date; /* save the original pointer */
int part = 0; /* max 6 parts */
while(*date && (part < 6)) {
bool found=FALSE;
skip(&date);
if(ISALPHA(*date)) {
/* a name coming up */
char buf[32]="";
size_t len;
sscanf(date, "%31[A-Za-z]", buf);
len = strlen(buf);
if(wdaynum == -1) {
wdaynum = checkday(buf, len);
if(wdaynum != -1)
found = TRUE;
}
if(!found && (monnum == -1)) {
monnum = checkmonth(buf);
if(monnum != -1)
found = TRUE;
}
if(!found && (tzoff == -1)) {
/* this just must be a time zone string */
tzoff = checktz(buf);
if(tzoff != -1)
found = TRUE;
}
if(!found)
return -1; /* bad string */
date += len;
}
else if(ISDIGIT(*date)) {
/* a digit */
int val;
char *end;
if((secnum == -1) &&
(3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
/* time stamp! */
date += 8;
found = TRUE;
}
else {
val = (int)strtol(date, &end, 10);
if((tzoff == -1) &&
((end - date) == 4) &&
(val < 1300) &&
(indate< date) &&
((date[-1] == '+' || date[-1] == '-'))) {
/* four digits and a value less than 1300 and it is preceeded with
a plus or minus. This is a time zone indication. */
found = TRUE;
tzoff = (val/100 * 60 + val%100)*60;
/* the + and - prefix indicates the local time compared to GMT,
this we need ther reversed math to get what we want */
tzoff = date[-1]=='+'?-tzoff:tzoff;
}
if(((end - date) == 8) &&
(yearnum == -1) &&
(monnum == -1) &&
(mdaynum == -1)) {
/* 8 digits, no year, month or day yet. This is YYYYMMDD */
found = TRUE;
yearnum = val/10000;
monnum = (val%10000)/100-1; /* month is 0 - 11 */
mdaynum = val%100;
}
if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) {
if((val > 0) && (val<32)) {
mdaynum = val;
found = TRUE;
}
dignext = DATE_YEAR;
}
if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) {
yearnum = val;
found = TRUE;
if(yearnum < 1900) {
if (yearnum > 70)
yearnum += 1900;
else
yearnum += 2000;
}
if(mdaynum == -1)
dignext = DATE_MDAY;
}
if(!found)
return -1;
date = end;
}
}
part++;
}
if(-1 == secnum)
secnum = minnum = hournum = 0; /* no time, make it zero */
if((-1 == mdaynum) ||
(-1 == monnum) ||
(-1 == yearnum))
/* lacks vital info, fail */
return -1;
#if SIZEOF_TIME_T < 5
/* 32 bit time_t can only hold dates to the beginning of 2038 */
if(yearnum > 2037)
return 0x7fffffff;
#endif
tm.tm_sec = secnum;
tm.tm_min = minnum;
tm.tm_hour = hournum;
tm.tm_mday = mdaynum;
tm.tm_mon = monnum;
tm.tm_year = yearnum - 1900;
tm.tm_wday = 0;
tm.tm_yday = 0;
tm.tm_isdst = 0;
/* mktime() returns a time_t. time_t is often 32 bits, even on many
architectures that feature 64 bit 'long'.
Some systems have 64 bit time_t and deal with years beyond 2038. However,
even some of the systems with 64 bit time_t returns -1 for dates beyond
03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
*/
t = mktime(&tm);
/* time zone adjust (cast t to int to compare to negative one) */
if(-1 != (int)t) {
struct tm *gmt;
long delta;
time_t t2;
#ifdef HAVE_GMTIME_R
/* thread-safe version */
struct tm keeptime2;
gmt = (struct tm *)gmtime_r(&t, &keeptime2);
if(!gmt)
return -1; /* illegal date/time */
t2 = mktime(gmt);
#else
/* It seems that at least the MSVC version of mktime() doesn't work
properly if it gets the 'gmt' pointer passed in (which is a pointer
returned from gmtime() pointing to static memory), so instead we copy
the tm struct to a local struct and pass a pointer to that struct as
input to mktime(). */
struct tm gmt2;
gmt = gmtime(&t); /* use gmtime_r() if available */
if(!gmt)
return -1; /* illegal date/time */
gmt2 = *gmt;
t2 = mktime(&gmt2);
#endif
/* Add the time zone diff (between the given timezone and GMT) and the
diff between the local time zone and GMT. */
delta = (long)((tzoff!=-1?tzoff:0) + (t - t2));
if((delta>0) && (t + delta < t))
return -1; /* time_t overflow */
t += delta;
}
return t;
}
time_t curl_getdate(const char *p, const time_t *now)
{
(void)now;
return Curl_parsedate(p);
}

View File

@ -0,0 +1,28 @@
#ifndef __PARSEDATE_H
#define __PARSEDATEL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, 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$
***************************************************************************/
extern const char * const Curl_wkday[7];
extern const char * const Curl_month[12];
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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
@ -139,10 +139,8 @@ void Curl_pgrsDone(struct connectdata *conn)
struct SessionHandle *data = conn->data;
data->progress.lastshow=0;
Curl_pgrsUpdate(conn); /* the final (forced) update */
if(!(data->progress.flags & PGRS_HIDE) &&
!data->progress.callback)
/* only output if we don't use a progress callback and we're not hidden */
fprintf(data->set.err, "\n");
data->progress.speeder_c = 0; /* reset the progress meter display */
}
/* reset all times except redirect */
@ -254,11 +252,11 @@ int Curl_pgrsUpdate(struct connectdata *conn)
even when not displayed! */
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if (!data->progress.callback) {
if(conn->resume_from)
if(data->reqdata.resume_from)
fprintf(data->set.err,
"** Resuming transfer from byte position %" FORMAT_OFF_T
"\n",
conn->resume_from);
data->reqdata.resume_from);
fprintf(data->set.err,
" %% Total %% Received %% Xferd Average Speed Time Time Time Current\n"
" Dload Upload Total Spent Left Speed\n");
@ -328,7 +326,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
curl_off_t amount = data->progress.speeder[nowindex]-
data->progress.speeder[checkindex];
if(amount > 0xffffffff/1000)
if(amount > 4294967 /* 0xffffffff/1000 */)
/* the 'amount' value is bigger than would fit in 32 bits if
multiplied with 1000, so we use the double math for this */
data->progress.current_speed = (curl_off_t)

View File

@ -1,10 +1,10 @@
#ifndef __PROGRESS_H
#define __PROGRESS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
@ -12,7 +12,7 @@
* 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.
@ -37,7 +37,7 @@ typedef enum {
TIMER_REDIRECT,
TIMER_LAST /* must be last */
} timerid;
void Curl_pgrsDone(struct connectdata *);
void Curl_pgrsStartNow(struct SessionHandle *data);
void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size);

View File

@ -46,7 +46,6 @@
#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
#include <curl/mprintf.h>
#include "security.h"
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
@ -55,17 +54,19 @@
#include <unistd.h>
#endif
#include "urldata.h"
#include "krb4.h"
#include "base64.h"
#include "sendf.h"
#include "ftp.h"
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
static struct {
static const struct {
enum protection_level level;
const char *name;
} level_names[] = {
@ -80,12 +81,12 @@ name_to_level(const char *name)
{
int i;
for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
if(!strncasecmp(level_names[i].name, name, strlen(name)))
if(curl_strnequal(level_names[i].name, name, strlen(name)))
return level_names[i].level;
return (enum protection_level)-1;
}
static struct Curl_sec_client_mech *mechs[] = {
static const struct Curl_sec_client_mech * const mechs[] = {
#ifdef KRB5
/* not supported */
#endif
@ -277,6 +278,13 @@ Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length)
return tx;
}
ssize_t
Curl_sec_send(struct connectdata *conn, int num, char *buffer, int length)
{
curl_socket_t fd = conn->sock[num];
return (ssize_t)Curl_sec_write(conn, fd, buffer, length);
}
int
Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
{
@ -297,13 +305,15 @@ int
Curl_sec_read_msg(struct connectdata *conn, char *s, int level)
{
int len;
char *buf;
unsigned char *buf;
int code;
buf = malloc(strlen(s));
len = Curl_base64_decode(s + 4, buf); /* XXX */
len = Curl_base64_decode(s + 4, &buf); /* XXX */
if(len > 0)
len = (conn->mech->decode)(conn->app_data, buf, len, level, conn);
else
return -1;
len = (conn->mech->decode)(conn->app_data, buf, len, level, conn);
if(len < 0) {
free(buf);
return -1;
@ -314,10 +324,10 @@ Curl_sec_read_msg(struct connectdata *conn, char *s, int level)
if(buf[3] == '-')
code = 0;
else
sscanf(buf, "%d", &code);
sscanf((char *)buf, "%d", &code);
if(buf[len-1] == '\n')
buf[len-1] = '\0';
strcpy(s, buf);
strcpy(s, (char *)buf);
free(buf);
return code;
}
@ -400,7 +410,7 @@ int
Curl_sec_login(struct connectdata *conn)
{
int ret;
struct Curl_sec_client_mech **m;
const struct Curl_sec_client_mech * const *m;
ssize_t nread;
struct SessionHandle *data=conn->data;
int ftpcode;

View File

@ -1,72 +0,0 @@
#ifndef __SECURITY_H
#define __SECURITY_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 a re-write */
#include <stdarg.h>
#include "urldata.h" /* for struct connectdata * */
struct Curl_sec_client_mech {
const char *name;
size_t size;
int (*init)(void *);
int (*auth)(void *, struct connectdata *);
void (*end)(void *);
int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
int (*encode)(void *, void*, int, int, void**, struct connectdata *);
int (*decode)(void *, void*, int, int, struct connectdata *);
};
#define AUTH_OK 0
#define AUTH_CONTINUE 1
#define AUTH_ERROR 2
extern struct Curl_sec_client_mech Curl_krb4_client_mech;
int Curl_sec_fflush_fd(struct connectdata *conn, int fd);
int Curl_sec_fprintf (struct connectdata *, FILE *, const char *, ...);
int Curl_sec_getc (struct connectdata *conn, FILE *);
int Curl_sec_putc (struct connectdata *conn, int, FILE *);
int Curl_sec_read (struct connectdata *conn, int, void *, int);
int Curl_sec_read_msg (struct connectdata *conn, char *, int);
int Curl_sec_vfprintf(struct connectdata *, FILE *, const char *, va_list);
int Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...);
int Curl_sec_vfprintf2(struct connectdata *conn, FILE *, const char *, va_list);
int Curl_sec_write (struct connectdata *conn, int, char *, int);
void Curl_sec_end (struct connectdata *);
int Curl_sec_login (struct connectdata *);
void Curl_sec_prot (int, char **);
int Curl_sec_request_prot (struct connectdata *conn, const char *level);
void Curl_sec_set_protection_level(struct connectdata *conn);
void Curl_sec_status (void);
enum protection_level Curl_set_command_prot(struct connectdata *,
enum protection_level);
#endif

315
Utilities/cmcurl/select.c Normal file
View File

@ -0,0 +1,315 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, 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 <errno.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifndef HAVE_SELECT
#error "We can't compile without select() support!"
#endif
#ifdef __BEOS__
/* BeOS has FD_SET defined in socket.h */
#include <socket.h>
#endif
#ifdef __MSDOS__
#include <dos.h> /* delay() */
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "connect.h"
#include "select.h"
#if defined(USE_WINSOCK) || defined(TPF)
#define VERIFY_SOCK(x) /* sockets are not in range [0..FD_SETSIZE] */
#else
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
#define VERIFY_SOCK(x) do { \
if(!VALID_SOCK(x)) { \
errno = EINVAL; \
return -1; \
} \
} while(0)
#endif
/*
* This is an internal function used for waiting for read or write
* events on single file descriptors. It attempts to replace select()
* in order to avoid limits with FD_SETSIZE.
*
* Return values:
* -1 = system call error
* 0 = timeout
* CSELECT_IN | CSELECT_OUT | CSELECT_ERR
*/
int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
{
#if defined(HAVE_POLL_FINE) || defined(CURL_HAVE_WSAPOLL)
struct pollfd pfd[2];
int num;
int r;
int ret;
num = 0;
if (readfd != CURL_SOCKET_BAD) {
pfd[num].fd = readfd;
pfd[num].events = POLLIN;
num++;
}
if (writefd != CURL_SOCKET_BAD) {
pfd[num].fd = writefd;
pfd[num].events = POLLOUT;
num++;
}
#ifdef HAVE_POLL_FINE
do {
r = poll(pfd, num, timeout_ms);
} while((r == -1) && (errno == EINTR));
#else
r = WSAPoll(pfd, num, timeout_ms);
#endif
if (r < 0)
return -1;
if (r == 0)
return 0;
ret = 0;
num = 0;
if (readfd != CURL_SOCKET_BAD) {
if (pfd[num].revents & (POLLIN|POLLHUP))
ret |= CSELECT_IN;
if (pfd[num].revents & POLLERR) {
#ifdef __CYGWIN__
/* Cygwin 1.5.21 needs this hack to pass test 160 */
if (errno == EINPROGRESS)
ret |= CSELECT_IN;
else
#endif
ret |= CSELECT_ERR;
}
num++;
}
if (writefd != CURL_SOCKET_BAD) {
if (pfd[num].revents & POLLOUT)
ret |= CSELECT_OUT;
if (pfd[num].revents & (POLLERR|POLLHUP))
ret |= CSELECT_ERR;
}
return ret;
#else
struct timeval timeout;
fd_set fds_read;
fd_set fds_write;
fd_set fds_err;
curl_socket_t maxfd;
int r;
int ret;
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
/* According to POSIX we should pass in NULL pointers if we don't want to
wait for anything in particular but just use the timeout function.
Windows however returns immediately if done so. I copied the MSDOS
delay() use from src/main.c that already had this work-around. */
#ifdef WIN32
Sleep(timeout_ms);
#elif defined(__MSDOS__)
delay(timeout_ms);
#else
select(0, NULL, NULL, NULL, &timeout);
#endif
return 0;
}
FD_ZERO(&fds_err);
maxfd = (curl_socket_t)-1;
FD_ZERO(&fds_read);
if (readfd != CURL_SOCKET_BAD) {
VERIFY_SOCK(readfd);
FD_SET(readfd, &fds_read);
FD_SET(readfd, &fds_err);
maxfd = readfd;
}
FD_ZERO(&fds_write);
if (writefd != CURL_SOCKET_BAD) {
VERIFY_SOCK(writefd);
FD_SET(writefd, &fds_write);
FD_SET(writefd, &fds_err);
if (writefd > maxfd)
maxfd = writefd;
}
do {
r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
} while((r == -1) && (Curl_sockerrno() == EINTR));
if (r < 0)
return -1;
if (r == 0)
return 0;
ret = 0;
if (readfd != CURL_SOCKET_BAD) {
if (FD_ISSET(readfd, &fds_read))
ret |= CSELECT_IN;
if (FD_ISSET(readfd, &fds_err))
ret |= CSELECT_ERR;
}
if (writefd != CURL_SOCKET_BAD) {
if (FD_ISSET(writefd, &fds_write))
ret |= CSELECT_OUT;
if (FD_ISSET(writefd, &fds_err))
ret |= CSELECT_ERR;
}
return ret;
#endif
}
/*
* This is a wrapper around poll(). If poll() does not exist, then
* select() is used instead. An error is returned if select() is
* being used and a file descriptor too large for FD_SETSIZE.
*
* Return values:
* -1 = system call error or fd >= FD_SETSIZE
* 0 = timeout
* 1 = number of structures with non zero revent fields
*/
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
{
int r;
#ifdef HAVE_POLL_FINE
do {
r = poll(ufds, nfds, timeout_ms);
} while((r == -1) && (errno == EINTR));
#elif defined(CURL_HAVE_WSAPOLL)
r = WSAPoll(ufds, nfds, timeout_ms);
#else
struct timeval timeout;
struct timeval *ptimeout;
fd_set fds_read;
fd_set fds_write;
fd_set fds_err;
curl_socket_t maxfd;
unsigned int i;
FD_ZERO(&fds_read);
FD_ZERO(&fds_write);
FD_ZERO(&fds_err);
maxfd = (curl_socket_t)-1;
for (i = 0; i < nfds; i++) {
if (ufds[i].fd == CURL_SOCKET_BAD)
continue;
#ifndef USE_WINSOCK /* winsock sockets are not in range [0..FD_SETSIZE] */
if (ufds[i].fd >= FD_SETSIZE) {
errno = EINVAL;
return -1;
}
#endif
if (ufds[i].fd > maxfd)
maxfd = ufds[i].fd;
if (ufds[i].events & POLLIN)
FD_SET(ufds[i].fd, &fds_read);
if (ufds[i].events & POLLOUT)
FD_SET(ufds[i].fd, &fds_write);
if (ufds[i].events & POLLERR)
FD_SET(ufds[i].fd, &fds_err);
}
if (timeout_ms < 0) {
ptimeout = NULL; /* wait forever */
} else {
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
ptimeout = &timeout;
}
do {
r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
} while((r == -1) && (Curl_sockerrno() == EINTR));
if (r < 0)
return -1;
if (r == 0)
return 0;
r = 0;
for (i = 0; i < nfds; i++) {
ufds[i].revents = 0;
if (ufds[i].fd == CURL_SOCKET_BAD)
continue;
if (FD_ISSET(ufds[i].fd, &fds_read))
ufds[i].revents |= POLLIN;
if (FD_ISSET(ufds[i].fd, &fds_write))
ufds[i].revents |= POLLOUT;
if (FD_ISSET(ufds[i].fd, &fds_err))
ufds[i].revents |= POLLERR;
if (ufds[i].revents != 0)
r++;
}
#endif
return r;
}
#ifdef TPF
/*
* This is a replacement for select() on the TPF platform.
* It is used whenever libcurl calls select().
* The call below to tpf_process_signals() is required because
* TPF's select calls are not signal interruptible.
*
* Return values are the same as select's.
*/
int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
fd_set* excepts, struct timeval* tv)
{
int rc;
rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
tpf_process_signals();
return(rc);
}
#endif /* TPF */

63
Utilities/cmcurl/select.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef __SELECT_H
#define __SELECT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, 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_SYS_POLL_H
#include <sys/poll.h>
#elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
/* for Vista, use WSAPoll(). */
#include <winsock2.h>
#define CURL_HAVE_WSAPOLL
#else
#define POLLIN 0x01
#define POLLPRI 0x02
#define POLLOUT 0x04
#define POLLERR 0x08
#define POLLHUP 0x10
#define POLLNVAL 0x20
struct pollfd
{
curl_socket_t fd;
short events;
short revents;
};
#endif
#define CSELECT_IN 0x01
#define CSELECT_OUT 0x02
#define CSELECT_ERR 0x04
int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms);
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
#ifdef TPF
int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
fd_set* excepts, struct timeval* tv);
#endif
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -43,16 +43,25 @@
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#include "connect.h" /* for the Curl_ourerrno() proto */
#include "connect.h" /* for the Curl_sockerrno() proto */
#include "sslgen.h"
#include "ssh.h"
#include "multiif.h"
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
#ifdef HAVE_KRB4
#include "security.h"
#include "krb4.h"
#else
#define Curl_sec_send(a,b,c,d) -1
#define Curl_sec_read(a,b,c,d) -1
#endif
#include <string.h>
#include "curl_memory.h"
#include "memory.h"
#include "strerror.h"
#include "easyif.h" /* for the Curl_convert_from_network prototype */
/* The last #include file should be: */
#include "memdebug.h"
@ -88,10 +97,10 @@ struct curl_slist *curl_slist_append(struct curl_slist *list,
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
char *cuDup = strdup(data);
if(cuDup) {
char *dup = strdup(data);
if(dup) {
new_item->next = NULL;
new_item->data = cuDup;
new_item->data = dup;
}
else {
free(new_item);
@ -132,17 +141,102 @@ void curl_slist_free_all(struct curl_slist *list)
} while (next);
}
#ifdef CURL_DO_LINEEND_CONV
/*
* convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
* (\n), with special processing for CRLF sequences that are split between two
* blocks of data. Remaining, bare CRs are changed to LFs. The possibly new
* size of the data is returned.
*/
static size_t convert_lineends(struct SessionHandle *data,
char *startPtr, size_t size)
{
char *inPtr, *outPtr;
/* sanity check */
if ((startPtr == NULL) || (size < 1)) {
return(size);
}
if (data->state.prev_block_had_trailing_cr == TRUE) {
/* The previous block of incoming data
had a trailing CR, which was turned into a LF. */
if (*startPtr == '\n') {
/* This block of incoming data starts with the
previous block's LF so get rid of it */
memcpy(startPtr, startPtr+1, size-1);
size--;
/* and it wasn't a bare CR but a CRLF conversion instead */
data->state.crlf_conversions++;
}
data->state.prev_block_had_trailing_cr = FALSE; /* reset the flag */
}
/* find 1st CR, if any */
inPtr = outPtr = memchr(startPtr, '\r', size);
if (inPtr) {
/* at least one CR, now look for CRLF */
while (inPtr < (startPtr+size-1)) {
/* note that it's size-1, so we'll never look past the last byte */
if (memcmp(inPtr, "\r\n", 2) == 0) {
/* CRLF found, bump past the CR and copy the NL */
inPtr++;
*outPtr = *inPtr;
/* keep track of how many CRLFs we converted */
data->state.crlf_conversions++;
}
else {
if (*inPtr == '\r') {
/* lone CR, move LF instead */
*outPtr = '\n';
}
else {
/* not a CRLF nor a CR, just copy whatever it is */
*outPtr = *inPtr;
}
}
outPtr++;
inPtr++;
} /* end of while loop */
if (inPtr < startPtr+size) {
/* handle last byte */
if (*inPtr == '\r') {
/* deal with a CR at the end of the buffer */
*outPtr = '\n'; /* copy a NL instead */
/* note that a CRLF might be split across two blocks */
data->state.prev_block_had_trailing_cr = TRUE;
}
else {
/* copy last byte */
*outPtr = *inPtr;
}
outPtr++;
inPtr++;
}
if (outPtr < startPtr+size) {
/* tidy up by null terminating the now shorter data */
*outPtr = '\0';
}
return(outPtr - startPtr);
}
return(size);
}
#endif /* CURL_DO_LINEEND_CONV */
/* Curl_infof() is for info message along the way */
void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
{
if(data && data->set.verbose) {
va_list ap;
size_t len;
char print_buffer[1024 + 1];
va_start(ap, fmt);
vsnprintf(print_buffer, 1024, fmt, ap);
va_end(ap);
Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer), NULL);
len = strlen(print_buffer);
Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
}
}
@ -153,25 +247,24 @@ void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
{
va_list ap;
size_t len;
va_start(ap, fmt);
if(data->set.errorbuffer && !data->state.errorbuf) {
vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap);
data->state.errorbuf = TRUE; /* wrote error string */
if(data->set.verbose) {
size_t len = strlen(data->set.errorbuffer);
bool doneit=FALSE;
if(len < CURL_ERROR_SIZE - 1) {
doneit = TRUE;
data->set.errorbuffer[len] = '\n';
data->set.errorbuffer[++len] = '\0';
}
Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len, NULL);
if(doneit)
/* cut off the newline again */
data->set.errorbuffer[--len]=0;
}
vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
if(data->set.errorbuffer && !data->state.errorbuf) {
snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
data->state.errorbuf = TRUE; /* wrote error string */
}
if(data->set.verbose) {
len = strlen(data->state.buffer);
if(len < BUFSIZE - 1) {
data->state.buffer[len] = '\n';
data->state.buffer[++len] = '\0';
}
Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
}
va_end(ap);
}
@ -182,7 +275,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
struct SessionHandle *data = conn->data;
ssize_t bytes_written;
size_t write_len;
CURLcode res;
CURLcode res = CURLE_OK;
char *s;
char *sptr;
va_list ap;
@ -204,8 +297,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
break;
if(data->set.verbose)
Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written,
conn->host.dispname);
Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
if((size_t)bytes_written != write_len) {
/* if not all was written at once, we must advance the pointer, decrease
@ -222,9 +314,40 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
return res;
}
static ssize_t Curl_plain_send(struct connectdata *conn,
int num,
void *mem,
size_t len)
{
curl_socket_t sockfd = conn->sock[num];
ssize_t bytes_written = swrite(sockfd, mem, len);
if(-1 == bytes_written) {
int err = Curl_sockerrno();
if(
#ifdef WSAEWOULDBLOCK
/* This is how Windows does it */
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We therefor
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
)
/* this is just a case of EWOULDBLOCK */
bytes_written=0;
else
failf(conn->data, "Send failure: %s",
Curl_strerror(conn, err));
}
return bytes_written;
}
/*
* Curl_write() is an internal write function that sends plain (binary) data
* to the server. Works with plain sockets, SSL or kerberos.
* Curl_write() is an internal write function that sends data to the
* server. Works with plain sockets, SCP, SSL or kerberos.
*/
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,
@ -234,84 +357,22 @@ CURLcode Curl_write(struct connectdata *conn,
{
ssize_t bytes_written;
CURLcode retcode;
#ifdef USE_SSLEAY
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets
us use the correct ssl handle. */
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
/* SSL_write() is said to return 'int' while write() and send() returns
'size_t' */
if (conn->ssl[num].use) {
int err;
char error_buffer[120]; /* OpenSSL documents that this must be at least
120 bytes long. */
unsigned long sslerror;
int rc = SSL_write(conn->ssl[num].handle, mem, (int)len);
if(rc < 0) {
err = SSL_get_error(conn->ssl[num].handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* The operation did not complete; the same TLS/SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
*written = 0;
return CURLE_OK;
case SSL_ERROR_SYSCALL:
failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
Curl_ourerrno());
return CURLE_SEND_ERROR;
case SSL_ERROR_SSL:
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
sslerror = ERR_get_error();
failf(conn->data, "SSL_write() error: %s\n",
ERR_error_string(sslerror, error_buffer));
return CURLE_SEND_ERROR;
}
/* a true error */
failf(conn->data, "SSL_write() return error %d\n", err);
return CURLE_SEND_ERROR;
}
bytes_written = rc;
}
else {
#else
(void)conn;
#endif
#ifdef HAVE_KRB4
if(conn->sec_complete) {
bytes_written = Curl_sec_write(conn, sockfd, mem, len);
}
else
#endif /* HAVE_KRB4 */
{
bytes_written = (ssize_t)swrite(sockfd, mem, len);
}
if(-1 == bytes_written) {
int err = Curl_ourerrno();
if(
#ifdef WSAEWOULDBLOCK
/* This is how Windows does it */
(WSAEWOULDBLOCK == err)
#else
/* As pointed out by Christophe Demory on March 11 2003, errno
may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We
therefor treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
)
/* this is just a case of EWOULDBLOCK */
bytes_written=0;
}
#ifdef USE_SSLEAY
}
#endif
if (conn->ssl[num].use)
/* only TRUE if SSL enabled */
bytes_written = Curl_ssl_send(conn, num, mem, len);
#ifdef USE_LIBSSH2
else if (conn->protocol & PROT_SCP)
bytes_written = Curl_scp_send(conn, num, mem, len);
else if (conn->protocol & PROT_SFTP)
bytes_written = Curl_sftp_send(conn, num, mem, len);
#endif /* !USE_LIBSSH2 */
else if(conn->sec_complete)
/* only TRUE if krb4 enabled */
bytes_written = Curl_sec_send(conn, num, mem, len);
else
bytes_written = Curl_plain_send(conn, num, mem, len);
*written = bytes_written;
retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
@ -324,23 +385,53 @@ CURLcode Curl_write(struct connectdata *conn,
The bit pattern defines to what "streams" to write to. Body and/or header.
The defines are in sendf.h of course.
*/
CURLcode Curl_client_write(struct SessionHandle *data,
CURLcode Curl_client_write(struct connectdata *conn,
int type,
char *ptr,
size_t len)
{
struct SessionHandle *data = conn->data;
size_t wrote;
if (data->state.cancelled) {
/* We just suck everything into a black hole */
return CURLE_OK;
}
if(0 == len)
len = strlen(ptr);
if(type & CLIENTWRITE_BODY) {
wrote = data->set.fwrite(ptr, 1, len, data->set.out);
if((conn->protocol&PROT_FTP) && conn->proto.ftpc.transfertype == 'A') {
#ifdef CURL_DOES_CONVERSIONS
/* convert from the network encoding */
size_t rc;
rc = Curl_convert_from_network(data, ptr, len);
/* Curl_convert_from_network calls failf if unsuccessful */
if(rc != CURLE_OK)
return rc;
#endif /* CURL_DOES_CONVERSIONS */
#ifdef CURL_DO_LINEEND_CONV
/* convert end-of-line markers */
len = convert_lineends(data, ptr, len);
#endif /* CURL_DO_LINEEND_CONV */
}
/* If the previous block of data ended with CR and this block of data is
just a NL, then the length might be zero */
if (len) {
wrote = data->set.fwrite(ptr, 1, len, data->set.out);
}
else {
wrote = len;
}
if(wrote != len) {
failf (data, "Failed writing body");
return CURLE_WRITE_ERROR;
}
}
if((type & CLIENTWRITE_HEADER) &&
(data->set.fwrite_header || data->set.writeheader) ) {
/*
@ -350,6 +441,9 @@ CURLcode Curl_client_write(struct SessionHandle *data,
curl_write_callback writeit=
data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
/* Note: The header is in the host encoding
regardless of the ftp transfer mode (ASCII/Image) */
wrote = writeit(ptr, 1, len, data->set.writeheader);
if(wrote != len) {
failf (data, "Failed writing header");
@ -360,6 +454,10 @@ CURLcode Curl_client_write(struct SessionHandle *data,
return CURLE_OK;
}
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/*
* Internal read-from-socket function. This is meant to deal with plain
* sockets, SSL sockets and kerberos sockets.
@ -370,11 +468,15 @@ CURLcode Curl_client_write(struct SessionHandle *data,
int Curl_read(struct connectdata *conn, /* connection data */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
size_t sizerequested, /* max amount to read */
ssize_t *n) /* amount bytes read */
{
ssize_t nread;
#ifdef USE_SSLEAY
size_t bytesfromsocket = 0;
char *buffertofill = NULL;
bool pipelining = (bool)(conn->data->multi &&
Curl_multi_canPipeline(conn->data->multi));
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
If it is the second socket, we set num to 1. Otherwise to 0. This lets
us use the correct ssl handle. */
@ -382,61 +484,75 @@ int Curl_read(struct connectdata *conn, /* connection data */
*n=0; /* reset amount to zero */
if (conn->ssl[num].use) {
nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, (int)buffersize);
/* If session can pipeline, check connection buffer */
if(pipelining) {
size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested);
if(nread < 0) {
/* failed SSL_read */
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
/* Copy from our master buffer first if we have some unread data there*/
if (bytestocopy > 0) {
memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy);
conn->read_pos += bytestocopy;
conn->bits.stream_was_rewound = FALSE;
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
case SSL_ERROR_ZERO_RETURN: /* no more data */
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke SSL_read() */
return -1; /* basicly EWOULDBLOCK */
default:
/* openssl/ssl.h says "look at error stack/return value/errno" */
{
char error_buffer[120]; /* OpenSSL documents that this must be at
least 120 bytes long. */
unsigned long sslerror = ERR_get_error();
failf(conn->data, "SSL read: %s, errno %d",
ERR_error_string(sslerror, error_buffer),
Curl_ourerrno() );
}
return CURLE_RECV_ERROR;
}
*n = (ssize_t)bytestocopy;
return CURLE_OK;
}
/* If we come here, it means that there is no data to read from the buffer,
* so we read from the socket */
bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer));
buffertofill = conn->master_buffer;
}
else {
#else
(void)conn;
#endif
*n=0; /* reset amount to zero */
#ifdef HAVE_KRB4
bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ?
conn->data->set.buffer_size : BUFSIZE);
buffertofill = buf;
}
if(conn->ssl[num].use) {
nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket);
if(nread == -1) {
return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */
}
}
#ifdef USE_LIBSSH2
else if (conn->protocol & PROT_SCP) {
nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
/* TODO: return CURLE_OK also for nread <= 0
read failures and timeouts ? */
}
else if (conn->protocol & PROT_SFTP) {
nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
}
#endif /* !USE_LIBSSH2 */
else {
if(conn->sec_complete)
nread = Curl_sec_read(conn, sockfd, buf, buffersize);
nread = Curl_sec_read(conn, sockfd, buffertofill,
bytesfromsocket);
else
#endif
nread = sread(sockfd, buf, buffersize);
nread = sread(sockfd, buffertofill, bytesfromsocket);
if(-1 == nread) {
int err = Curl_ourerrno();
#ifdef WIN32
int err = Curl_sockerrno();
#ifdef USE_WINSOCK
if(WSAEWOULDBLOCK == err)
#else
if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
#endif
return -1;
}
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
*n = nread;
if (nread >= 0) {
if(pipelining) {
memcpy(buf, conn->master_buffer, nread);
conn->buf_len = nread;
conn->read_pos = nread;
}
*n += nread;
}
return CURLE_OK;
}
@ -447,6 +563,46 @@ static int showit(struct SessionHandle *data, curl_infotype type,
static const char * const s_infotype[CURLINFO_END] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
#ifdef CURL_DOES_CONVERSIONS
char buf[BUFSIZE+1];
size_t conv_size = 0;
switch(type) {
case CURLINFO_HEADER_OUT:
/* assume output headers are ASCII */
/* copy the data into my buffer so the original is unchanged */
if (size > BUFSIZE) {
size = BUFSIZE; /* truncate if necessary */
buf[BUFSIZE] = '\0';
}
conv_size = size;
memcpy(buf, ptr, size);
/* Special processing is needed for this block if it
* contains both headers and data (separated by CRLFCRLF).
* We want to convert just the headers, leaving the data as-is.
*/
if(size > 4) {
size_t i;
for(i = 0; i < size-4; i++) {
if(memcmp(&buf[i], "\x0d\x0a\x0d\x0a", 4) == 0) {
/* convert everthing through this CRLFCRLF but no further */
conv_size = i + 4;
break;
}
}
}
Curl_convert_from_network(data, buf, conv_size);
/* Curl_convert_from_network calls failf if unsuccessful */
/* we might as well continue even if it fails... */
ptr = buf; /* switch pointer to use my buffer instead */
break;
default:
/* leave everything else as-is */
break;
}
#endif /* CURL_DOES_CONVERSIONS */
if(data->set.fdebug)
return (*data->set.fdebug)(data, type, ptr, size,
data->set.debugdata);
@ -457,6 +613,12 @@ static int showit(struct SessionHandle *data, curl_infotype type,
case CURLINFO_HEADER_IN:
fwrite(s_infotype[type], 2, 1, data->set.err);
fwrite(ptr, size, 1, data->set.err);
#ifdef CURL_DOES_CONVERSIONS
if(size != conv_size) {
/* we had untranslated data so we need an explicit newline */
fwrite("\n", 1, 1, data->set.err);
}
#endif
break;
default: /* nada */
break;
@ -465,18 +627,22 @@ static int showit(struct SessionHandle *data, curl_infotype type,
}
int Curl_debug(struct SessionHandle *data, curl_infotype type,
char *ptr, size_t size, char *host)
char *ptr, size_t size,
struct connectdata *conn)
{
int rc;
if(data->set.printhost && host) {
if(data->set.printhost && conn && conn->host.dispname) {
char buffer[160];
const char *t=NULL;
const char *w="Data";
switch (type) {
case CURLINFO_HEADER_IN:
w = "Header";
case CURLINFO_DATA_IN:
t = "from";
break;
case CURLINFO_HEADER_OUT:
w = "Header";
case CURLINFO_DATA_OUT:
t = "to";
break;
@ -485,7 +651,8 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
}
if(t) {
snprintf(buffer, sizeof(buffer), "[Data %s %s]", t, host);
snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
conn->host.dispname);
rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
if(rc)
return rc;

View File

@ -1,18 +1,18 @@
#ifndef __SENDF_H
#define __SENDF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, 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.
@ -28,16 +28,31 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *,
void Curl_infof(struct SessionHandle *, const char *fmt, ...);
void Curl_failf(struct SessionHandle *, const char *fmt, ...);
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
#if defined(__GNUC__)
/* This style of variable argument macros is a gcc extension */
#define infof(x...) /*ignore*/
#else
/* C99 compilers could use this if we could detect them */
/*#define infof(...) */
/* Cast the args to void to make them a noop, side effects notwithstanding */
#define infof (void)
#endif
#else
#define infof Curl_infof
#endif
#define failf Curl_failf
#define CLIENTWRITE_BODY 1
#define CLIENTWRITE_HEADER 2
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr,
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len);
void Curl_read_rewind(struct connectdata *conn,
size_t extraBytesRead);
/* internal read-function, does plain socket, SSL and krb4 */
int Curl_read(struct connectdata *conn, curl_socket_t sockfd,
char *buf, size_t buffersize,
@ -50,7 +65,8 @@ CURLcode Curl_write(struct connectdata *conn,
/* the function used to output verbose information */
int Curl_debug(struct SessionHandle *handle, curl_infotype type,
char *data, size_t size, char *host);
char *data, size_t size,
struct connectdata *conn);
#endif

View File

@ -1,5 +1,5 @@
#ifndef __SETUP_H
#define __SETUP_H
#ifndef __LIB_CURL_SETUP_H
#define __LIB_CURL_SETUP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2007, 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
@ -24,37 +24,104 @@
***************************************************************************/
#ifdef HTTP_ONLY
#define CURL_DISABLE_TFTP
#define CURL_DISABLE_FTP
#define CURL_DISABLE_LDAP
#define CURL_DISABLE_TELNET
#define CURL_DISABLE_DICT
#define CURL_DISABLE_FILE
#define CURL_DISABLE_GOPHER
#endif
#endif /* HTTP_ONLY */
#if !defined(WIN32) && defined(__WIN32__)
/* This should be a good Borland fix. Alexander J. Oss told us! */
/* Borland fix */
#define WIN32
#endif
#if !defined(WIN32) && defined(_WIN32)
/* VS2005 on x64 fix */
#define WIN32
#endif
/*
* Include configuration script results or hand-crafted
* configuration file for platforms which lack config tool.
*/
#ifdef HAVE_CONFIG_H
#include "config.h" /* the configure script results */
#include "config.h"
#else
/*
#ifdef _WIN32_WCE
#include "config-win32ce.h"
#else
#ifdef WIN32
/* hand-modified win32 config.h! */
#include "config-win32.h"
#endif
#endif
*/
#ifdef macintosh
/* hand-modified MacOS config.h! */
#include "config-mac.h"
#endif
#ifdef AMIGA
/* hand-modified AmigaOS config.h! */
#include "amigaos.h"
#endif
#ifdef TPF
#include "config-tpf.h" /* hand-modified TPF config.h */
/* change which select is used for libcurl */
#define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e)
#endif
#endif /* HAVE_CONFIG_H */
/*
* Include header files for windows builds before redefining anything.
* Use this preproessor block only to include or exclude windows.h,
* winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs
* to any other further and independant block. Under Cygwin things work
* just as under linux (e.g. <sys/socket.h>) and the winsock headers should
* never be included when __CYGWIN__ is defined. configure script takes
* care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H,
* neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
*/
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# ifdef HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# endif
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif
#endif
/*
* Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
* define USE_WINSOCK to 1 if we have and use WINSOCK API, else
* undefine USE_WINSOCK.
*/
#undef USE_WINSOCK
#ifdef HAVE_WINSOCK2_H
# define USE_WINSOCK 2
#else
# ifdef HAVE_WINSOCK_H
# define USE_WINSOCK 1
# endif
#endif
#ifndef TRUE
#define TRUE 1
#endif
@ -62,7 +129,7 @@
#define FALSE 0
#endif
#if !defined(__cplusplus) && !defined(__BEOS__)
#if !defined(__cplusplus) && !defined(__BEOS__) && !defined(__ECOS) && !defined(typedef_bool)
typedef unsigned char bool;
#define typedef_bool
#endif
@ -74,7 +141,7 @@ typedef unsigned char bool;
#ifdef _MSC_VER
#define LONG_LONG __int64
#define ENABLE_64BIT
#endif
#endif /* _MSC_VER */
#endif /* HAVE_LONGLONG */
#ifndef SIZEOF_CURL_OFF_T
@ -89,12 +156,13 @@ typedef unsigned char bool;
#define FORMAT_OFF_T "lld"
#else
#define FORMAT_OFF_T "ld"
#endif
#endif /* SIZEOF_CURL_OFF_T */
#ifdef NEED_REENTRANT
/* Solaris machines needs _REENTRANT set for a few function prototypes and
things to appear in the #include files. We need to #define it before all
#include files */
#ifndef _REENTRANT
/* Solaris needs _REENTRANT set for a few function prototypes and things to
appear in the #include files. We need to #define it before all #include
files. Unixware needs it to build proper reentrant code. Others may also
need it. */
#define _REENTRANT
#endif
@ -108,27 +176,36 @@ typedef unsigned char bool;
#include <floss.h>
#endif
#if defined(HAVE_X509_H) && defined(HAVE_SSL_H) && defined(HAVE_RSA_H) && \
defined(HAVE_PEM_H) && defined(HAVE_ERR_H) && defined(HAVE_CRYPTO_H) && \
defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
/* the six important includes files all exist and so do both libs,
defined SSLeay usage */
#define USE_SSLEAY 1
#endif
#if defined(HAVE_OPENSSL_X509_H) && defined(HAVE_OPENSSL_SSL_H) && \
defined(HAVE_OPENSSL_RSA_H) && defined(HAVE_OPENSSL_PEM_H) && \
defined(HAVE_OPENSSL_ERR_H) && defined(HAVE_OPENSSL_CRYPTO_H) && \
defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
/* the six important includes files all exist and so do both libs,
defined SSLeay usage */
#define USE_SSLEAY 1
#define USE_OPENSSL 1
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
#include <curl/stdcheaders.h>
#endif
/*
* PellesC cludge section (yikes);
* - It has 'ssize_t', but it is in <unistd.h>. The way the headers
* on Win32 are included, forces me to include this header here.
* - sys_nerr, EINTR is missing in v4.0 or older.
*/
#ifdef __POCC__
#include <sys/types.h>
#include <unistd.h>
#if (__POCC__ <= 400)
#define sys_nerr EILSEQ /* for strerror.c */
#define EINTR -1 /* for select.c */
#endif
#endif
/*
* Salford-C cludge section (mostly borrowed from wxWidgets).
*/
#ifdef __SALFORDC__
#pragma suppress 353 /* Possible nested comments */
#pragma suppress 593 /* Define not used */
#pragma suppress 61 /* enum has no name */
#pragma suppress 106 /* unnamed, unused parameter */
#include <clib.h>
#endif
#if defined(CURLDEBUG) && defined(HAVE_ASSERT_H)
#define curlassert(x) assert(x)
#else
@ -136,20 +213,22 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#define curlassert(x)
#endif
#ifdef MSG_NOSIGNAL
/* If we have the MSG_NOSIGNAL define, we make sure to use that in the forth
argument to send() and recv() */
#define SEND_4TH_ARG MSG_NOSIGNAL
#define HAVE_MSG_NOSIGNAL 1 /* we have MSG_NOSIGNAL */
/* To make large file support transparent even on Windows */
#if defined(WIN32) && (SIZEOF_CURL_OFF_T > 4)
#include <sys/stat.h> /* must come first before we redefine stat() */
#include <io.h>
#define lseek(x,y,z) _lseeki64(x, y, z)
#define struct_stat struct _stati64
#define stat(file,st) _stati64(file,st)
#define fstat(fd,st) _fstati64(fd,st)
#else
#define SEND_4TH_ARG 0
#endif
#define struct_stat struct stat
#endif /* Win32 with large file support */
/* Below we define four functions. They should
/* Below we define some functions. They should
1. close a socket
2. read from a socket
3. write to a socket
4. set the SIGALRM signal timeout
5. set dir/file naming defines
@ -157,49 +236,24 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN /* Prevent including <winsock*.h> in <windows.h> */
#endif
#if (defined(ENABLE_IPV6) || defined(CURLDEBUG)) && defined(_MSC_VER) && \
(!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0500)
/*
* Needed to pull in the real getaddrinfo() and not the inline version
* in <wspiAPI.H> which doesn't support IPv6 (IPv4 only). <wspiAPI.H> is
* included from <ws2tcpip.h> for <= 0x0500 SDKs.
*/
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <winsock2.h> /* required by telnet.c */
#if defined(ENABLE_IPV6) || defined(USE_SSLEAY)
#include <ws2tcpip.h>
#endif
#if !defined(__GNUC__) || defined(__MINGW32__)
#if !defined(__CYGWIN__)
#define sclose(x) closesocket(x)
#define sread(x,y,z) recv(x,y,z, SEND_4TH_ARG)
#define swrite(x,y,z) (size_t)send(x,y,z, SEND_4TH_ARG)
#undef HAVE_ALARM
#else
/* gcc-for-win is still good :) */
#define sclose(x) close(x)
#define sread(x,y,z) recv(x,y,z, SEND_4TH_ARG)
#define swrite(x,y,z) send(x,y,z, SEND_4TH_ARG)
#define HAVE_ALARM
#endif
#endif /* !GNU or mingw */
#define DIR_CHAR "\\"
#define DOT_CHAR "_"
#else
#else /* WIN32 */
#ifdef DJGPP
#ifdef MSDOS /* Watt-32 */
#include <sys/ioctl.h>
#define sclose(x) close_s(x)
#define sread(x,y,z) read_s(x,y,z)
#define swrite(x,y,z) write_s(x,y,z)
#define select(n,r,w,x,t) select_s(n,r,w,x,t)
#define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
#define IOCTL_3_ARGS
@ -208,21 +262,17 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#undef word
#endif
#else
#else /* MSDOS */
#ifdef __BEOS__
#define sclose(x) closesocket(x)
#define sread(x,y,z) (ssize_t)recv(x,y,z, SEND_4TH_ARG)
#define swrite(x,y,z) (ssize_t)send(x,y,z, SEND_4TH_ARG)
#else
#else /* __BEOS__ */
#define sclose(x) close(x)
#define sread(x,y,z) recv(x,y,z, SEND_4TH_ARG)
#define swrite(x,y,z) send(x,y,z, SEND_4TH_ARG)
#endif
#endif /* __BEOS__ */
#define HAVE_ALARM
#endif
#endif /* MSDOS */
#ifdef _AMIGASF
#undef HAVE_ALARM
@ -231,9 +281,11 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#endif
#define DIR_CHAR "/"
#ifndef DOT_CHAR
#define DOT_CHAR "."
#endif
#ifdef DJGPP
#ifdef MSDOS
#undef DOT_CHAR
#define DOT_CHAR "_"
#endif
@ -242,20 +294,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
int fileno( FILE *stream);
#endif
#endif
/* now typedef our socket type */
#ifdef WIN32
typedef SOCKET curl_socket_t;
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
typedef int curl_socket_t;
#define CURL_SOCKET_BAD -1
#endif
#if defined(ENABLE_IPV6) && defined(USE_ARES)
#error "ares does not yet support IPv6. Disable IPv6 or ares and rebuild"
#endif
#endif /* WIN32 */
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(USE_ARES) && \
!defined(__LCC__) /* lcc-win32 doesn't have _beginthreadex() */
@ -266,29 +305,78 @@ typedef int curl_socket_t;
#endif
#endif
#ifdef mpeix
#define IOCTL_3_ARGS
/* "cl -ML" or "cl -MLd" implies a single-threaded runtime library where
_beginthreadex() is not available */
#if (defined(_MSC_VER) && !defined(__POCC__)) && !defined(_MT) && !defined(USE_ARES)
#undef USE_THREADING_GETADDRINFO
#undef USE_THREADING_GETHOSTBYNAME
#define CURL_NO__BEGINTHREADEX
#endif
#ifndef ECONNRESET
#ifdef WSAECONNRESET
#define ECONNRESET WSAECONNRESET
#else
/* This will effectively prevent the code from working in this particular
aspect, but it still compile fine! */
#define ECONNRESET 10000
/*
* msvc 6.0 does not have struct sockaddr_storage and
* does not define IPPROTO_ESP in winsock2.h. But both
* are available if PSDK is properly installed.
*/
#ifdef _MSC_VER
#if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
#undef HAVE_STRUCT_SOCKADDR_STORAGE
#endif
#endif
#ifdef mpeix
#define IOCTL_3_ARGS
#endif
#ifdef NETWARE
#undef HAVE_ALARM
#endif
#ifdef HAVE_LIBIDN
/* This could benefit from additional checks that some of the used/important
header files are present as well before we define the USE_* define. */
#if defined(HAVE_LIBIDN) && defined(HAVE_TLD_H)
/* The lib was present and the tld.h header (which is missing in libidn 0.3.X
but we only work with libidn 0.4.1 or later) */
#define USE_LIBIDN
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#endif
#endif /* __CONFIG_H */
#ifndef SIZEOF_TIME_T
/* assume default size of time_t to be 32 bit */
#define SIZEOF_TIME_T 4
#endif
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#ifdef __UCLIBC__
#define HAVE_INET_NTOA_R_2_ARGS 1
#endif
#if defined(USE_GNUTLS) || defined(USE_SSLEAY)
#define USE_SSL /* Either OpenSSL || GnuTLS */
#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM)
#if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI)
#define USE_NTLM
#endif
#endif
#ifdef CURLDEBUG
#define DEBUGF(x) x
#else
#define DEBUGF(x)
#endif
/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */
#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE)
#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
#endif
/*
* Include macros and defines that should only be processed once.
*/
#ifndef __SETUP_ONCE_H
#include "setup_once.h"
#endif
#endif /* __LIB_CURL_SETUP_H */

View File

@ -0,0 +1,153 @@
#ifndef __SETUP_ONCE_H
#define __SETUP_ONCE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, 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$
***************************************************************************/
/********************************************************************
* NOTICE *
* ======== *
* *
* Content of header files lib/setup_once.h and ares/setup_once.h *
* must be kept in sync. Modify the other one if you change this. *
* *
********************************************************************/
/*
* If we have the MSG_NOSIGNAL define, make sure we use
* it as the fourth argument of function send()
*/
#ifdef HAVE_MSG_NOSIGNAL
#define SEND_4TH_ARG MSG_NOSIGNAL
#else
#define SEND_4TH_ARG 0
#endif
/*
* The definitions for the return type and arguments types
* of functions recv() and send() belong and come from the
* configuration file. Do not define them in any other place.
*
* HAVE_RECV is defined if you have a function named recv()
* which is used to read incoming data from sockets. If your
* function has another name then don't define HAVE_RECV.
*
* If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2,
* RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also
* be defined.
*
* HAVE_SEND is defined if you have a function named send()
* which is used to write outgoing data on a connected socket.
* If yours has another name then don't define HAVE_SEND.
*
* If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2,
* SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and
* SEND_TYPE_RETV must also be defined.
*/
#ifdef HAVE_RECV
#if !defined(RECV_TYPE_ARG1) || \
!defined(RECV_TYPE_ARG2) || \
!defined(RECV_TYPE_ARG3) || \
!defined(RECV_TYPE_ARG4) || \
!defined(RECV_TYPE_RETV)
/* */
Error Missing_definition_of_return_and_arguments_types_of_recv
/* */
#else
#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \
(RECV_TYPE_ARG2)(y), \
(RECV_TYPE_ARG3)(z), \
(RECV_TYPE_ARG4)(0))
#endif
#else /* HAVE_RECV */
#ifndef sread
/* */
Error Missing_definition_of_macro_sread
/* */
#endif
#endif /* HAVE_RECV */
#ifdef HAVE_SEND
#if !defined(SEND_TYPE_ARG1) || \
!defined(SEND_QUAL_ARG2) || \
!defined(SEND_TYPE_ARG2) || \
!defined(SEND_TYPE_ARG3) || \
!defined(SEND_TYPE_ARG4) || \
!defined(SEND_TYPE_RETV)
/* */
Error Missing_definition_of_return_and_arguments_types_of_send
/* */
#else
#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
(SEND_TYPE_ARG2)(y), \
(SEND_TYPE_ARG3)(z), \
(SEND_TYPE_ARG4)(SEND_4TH_ARG))
#endif
#else /* HAVE_SEND */
#ifndef swrite
/* */
Error Missing_definition_of_macro_swrite
/* */
#endif
#endif /* HAVE_SEND */
/*
* Uppercase macro versions of ANSI/ISO is*() functions/macros which
* avoid negative number inputs with argument byte codes > 127.
*/
#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
/*
* Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
*/
#ifndef HAVE_SIG_ATOMIC_T
typedef int sig_atomic_t;
#define HAVE_SIG_ATOMIC_T
#endif
/*
* Default return type for signal handlers.
*/
#ifndef RETSIGTYPE
#define RETSIGTYPE void
#endif
#endif /* __SETUP_ONCE_H */

View File

@ -28,7 +28,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "share.h"
#include "curl_memory.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -77,7 +77,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
}
break;
#ifndef CURL_DISABLE_HTTP
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
case CURL_LOCK_DATA_COOKIE:
if (!share->cookies) {
share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE );
@ -108,7 +108,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
}
break;
#ifndef CURL_DISABLE_HTTP
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
case CURL_LOCK_DATA_COOKIE:
if (share->cookies) {
Curl_cookie_cleanup(share->cookies);
@ -171,7 +171,7 @@ curl_share_cleanup(CURLSH *sh)
if(share->hostcache)
Curl_hash_destroy(share->hostcache);
#ifndef CURL_DISABLE_HTTP
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(share->cookies)
Curl_cookie_cleanup(share->cookies);
#endif /* CURL_DISABLE_HTTP */

View File

@ -2,18 +2,18 @@
#define __CURL_SHARE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2005, 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.
@ -28,28 +28,29 @@
#include <curl/curl.h>
#include "cookie.h"
/* SalfordC says "A structure member may not be volatile". Hence:
*/
#ifdef __SALFORDC__
#define CURL_VOLATILE
#else
#define CURL_VOLATILE volatile
#endif
/* this struct is libcurl-private, don't export details */
struct Curl_share {
unsigned int specifier;
volatile unsigned int dirty;
CURL_VOLATILE unsigned int dirty;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
void *clientdata;
curl_hash *hostcache;
struct curl_hash *hostcache;
struct CookieInfo *cookies;
};
CURLSHcode Curl_share_lock (
struct SessionHandle *,
curl_lock_data,
curl_lock_access
);
CURLSHcode Curl_share_unlock (
struct SessionHandle *,
curl_lock_data
);
CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
curl_lock_access);
CURLSHcode Curl_share_unlock (struct SessionHandle *, curl_lock_data);
#endif /* __CURL_SHARE_H */

View File

@ -0,0 +1,38 @@
#ifndef __SOCKADDR_H
#define __SOCKADDR_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, 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_STRUCT_SOCKADDR_STORAGE
struct Curl_sockaddr_storage {
struct sockaddr_storage buffer;
};
#else
struct Curl_sockaddr_storage {
char buffer[256]; /* this should be big enough to fit a lot */
};
#endif
#endif /* __SOCKADDR_H */

585
Utilities/cmcurl/socks.c Normal file
View File

@ -0,0 +1,585 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, 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>
#ifdef NEED_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "select.h"
#include "connect.h"
#include "timeval.h"
#include "socks.h"
/* The last #include file should be: */
#include "memdebug.h"
/*
* Helper read-from-socket functions. Does the same as Curl_read() but it
* blocks until all bytes amount of buffersize will be read. No more, no less.
*
* This is STUPID BLOCKING behaviour which we frown upon, but right now this
* is what we have...
*/
static int blockread_all(struct connectdata *conn, /* connection data */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
ssize_t buffersize, /* max amount to read */
ssize_t *n, /* amount bytes read */
long conn_timeout) /* timeout for data wait
relative to
conn->created */
{
ssize_t nread;
ssize_t allread = 0;
int result;
struct timeval tvnow;
long conntime;
*n = 0;
do {
tvnow = Curl_tvnow();
/* calculating how long connection is establishing */
conntime = Curl_tvdiff(tvnow, conn->created);
if(conntime > conn_timeout) {
/* we already got the timeout */
result = ~CURLE_OK;
break;
}
if(Curl_select(sockfd, CURL_SOCKET_BAD,
(int)(conn_timeout - conntime)) <= 0) {
result = ~CURLE_OK;
break;
}
result = Curl_read(conn, sockfd, buf, buffersize, &nread);
if(result)
break;
if(buffersize == nread) {
allread += nread;
*n = allread;
result = CURLE_OK;
break;
}
buffersize -= nread;
buf += nread;
allread += nread;
} while(1);
return result;
}
/*
* This function logs in to a SOCKS4 proxy and sends the specifics to the final
* destination server.
*
* Reference :
* http://socks.permeo.com/protocol/socks4.protocol
*
* Note :
* Nonsupport "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
* Nonsupport "Identification Protocol (RFC1413)"
*/
CURLcode Curl_SOCKS4(const char *proxy_name,
struct connectdata *conn)
{
unsigned char socksreq[262]; /* room for SOCKS4 request incl. user id */
int result;
CURLcode code;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
long timeout;
struct SessionHandle *data = conn->data;
/* get timeout */
if(data->set.timeout && data->set.connecttimeout) {
if (data->set.timeout < data->set.connecttimeout)
timeout = data->set.timeout*1000;
else
timeout = data->set.connecttimeout*1000;
}
else if(data->set.timeout)
timeout = data->set.timeout*1000;
else if(data->set.connecttimeout)
timeout = data->set.connecttimeout*1000;
else
timeout = DEFAULT_CONNECT_TIMEOUT;
Curl_nonblock(sock, FALSE);
/*
* Compose socks4 request
*
* Request format
*
* +----+----+----+----+----+----+----+----+----+----+....+----+
* | VN | CD | DSTPORT | DSTIP | USERID |NULL|
* +----+----+----+----+----+----+----+----+----+----+....+----+
* # of bytes: 1 1 2 4 variable 1
*/
socksreq[0] = 4; /* version (SOCKS4) */
socksreq[1] = 1; /* connect */
*((unsigned short*)&socksreq[2]) = htons(conn->remote_port);
/* DNS resolve */
{
struct Curl_dns_entry *dns;
Curl_addrinfo *hp=NULL;
int rc;
rc = Curl_resolv(conn, conn->host.name, (int)conn->remote_port, &dns);
if(rc == CURLRESOLV_ERROR)
return CURLE_COULDNT_RESOLVE_PROXY;
if(rc == CURLRESOLV_PENDING)
/* this requires that we're in "wait for resolve" state */
rc = Curl_wait_for_resolv(conn, &dns);
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
* returns a Curl_addrinfo pointer that may not always look the same.
*/
if(dns)
hp=dns->addr;
if (hp) {
char buf[64];
unsigned short ip[4];
Curl_printable_address(hp, buf, sizeof(buf));
if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3])) {
/* Set DSTIP */
socksreq[4] = (unsigned char)ip[0];
socksreq[5] = (unsigned char)ip[1];
socksreq[6] = (unsigned char)ip[2];
socksreq[7] = (unsigned char)ip[3];
}
else
hp = NULL; /* fail! */
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
conn->host.name);
return CURLE_COULDNT_RESOLVE_HOST;
}
}
/*
* This is currently not supporting "Identification Protocol (RFC1413)".
*/
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
if (proxy_name)
strlcat((char*)socksreq + 8, proxy_name, sizeof(socksreq) - 8);
/*
* Make connection
*/
{
ssize_t actualread;
ssize_t written;
int packetsize = 9 +
(int)strlen((char*)socksreq + 8); /* size including NUL */
/* Send request */
code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
if ((code != CURLE_OK) || (written != packetsize)) {
failf(data, "Failed to send SOCKS4 connect request.");
return CURLE_COULDNT_CONNECT;
}
packetsize = 8; /* receive data size */
/* Receive response */
result = blockread_all(conn, sock, (char *)socksreq, packetsize,
&actualread, timeout);
if ((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS4 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
/*
* Response format
*
* +----+----+----+----+----+----+----+----+
* | VN | CD | DSTPORT | DSTIP |
* +----+----+----+----+----+----+----+----+
* # of bytes: 1 1 2 4
*
* VN is the version of the reply code and should be 0. CD is the result
* code with one of the following values:
*
* 90: request granted
* 91: request rejected or failed
* 92: request rejected because SOCKS server cannot connect to
* identd on the client
* 93: request rejected because the client program and identd
* report different user-ids
*/
/* wrong version ? */
if (socksreq[0] != 0) {
failf(data,
"SOCKS4 reply has wrong version, version should be 4.");
return CURLE_COULDNT_CONNECT;
}
/* Result */
switch(socksreq[1])
{
case 90:
infof(data, "SOCKS4 request granted.\n");
break;
case 91:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected or failed.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
socksreq[1]);
return CURLE_COULDNT_CONNECT;
case 92:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected because SOCKS server cannot connect to "
"identd on the client.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
socksreq[1]);
return CURLE_COULDNT_CONNECT;
case 93:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", request rejected because the client program and identd "
"report different user-ids.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
socksreq[1]);
return CURLE_COULDNT_CONNECT;
default:
failf(data,
"Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
", Unknown.",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
socksreq[1]);
return CURLE_COULDNT_CONNECT;
}
}
Curl_nonblock(sock, TRUE);
return CURLE_OK; /* Proxy was successful! */
}
/*
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
*/
CURLcode Curl_SOCKS5(const char *proxy_name,
const char *proxy_password,
struct connectdata *conn)
{
/*
According to the RFC1928, section "6. Replies". This is what a SOCK5
replies:
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
Where:
o VER protocol version: X'05'
o REP Reply field:
o X'00' succeeded
*/
unsigned char socksreq[600]; /* room for large user/pw (255 max each) */
ssize_t actualread;
ssize_t written;
int result;
CURLcode code;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
struct SessionHandle *data = conn->data;
long timeout;
/* get timeout */
if(data->set.timeout && data->set.connecttimeout) {
if (data->set.timeout < data->set.connecttimeout)
timeout = data->set.timeout*1000;
else
timeout = data->set.connecttimeout*1000;
}
else if(data->set.timeout)
timeout = data->set.timeout*1000;
else if(data->set.connecttimeout)
timeout = data->set.connecttimeout*1000;
else
timeout = DEFAULT_CONNECT_TIMEOUT;
Curl_nonblock(sock, TRUE);
/* wait until socket gets connected */
result = Curl_select(CURL_SOCKET_BAD, sock, (int)timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5: no connection here");
return CURLE_COULDNT_CONNECT;
}
else if(0 == result) {
failf(conn->data, "SOCKS5: connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
if(result & CSELECT_ERR) {
failf(conn->data, "SOCKS5: error occured during connection");
return CURLE_COULDNT_CONNECT;
}
socksreq[0] = 5; /* version */
socksreq[1] = (char)(proxy_name ? 2 : 1); /* number of methods (below) */
socksreq[2] = 0; /* no authentication */
socksreq[3] = 2; /* username/password */
Curl_nonblock(sock, FALSE);
code = Curl_write(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
&written);
if ((code != CURLE_OK) || (written != (2 + (int)socksreq[1]))) {
failf(data, "Unable to send initial SOCKS5 request.");
return CURLE_COULDNT_CONNECT;
}
Curl_nonblock(sock, TRUE);
result = Curl_select(sock, CURL_SOCKET_BAD, (int)timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5 nothing to read");
return CURLE_COULDNT_CONNECT;
}
else if(0 == result) {
failf(conn->data, "SOCKS5 read timeout");
return CURLE_OPERATION_TIMEDOUT;
}
if(result & CSELECT_ERR) {
failf(conn->data, "SOCKS5 read error occured");
return CURLE_RECV_ERROR;
}
Curl_nonblock(sock, FALSE);
result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread, timeout);
if ((result != CURLE_OK) || (actualread != 2)) {
failf(data, "Unable to receive initial SOCKS5 response.");
return CURLE_COULDNT_CONNECT;
}
if (socksreq[0] != 5) {
failf(data, "Received invalid version in initial SOCKS5 response.");
return CURLE_COULDNT_CONNECT;
}
if (socksreq[1] == 0) {
/* Nothing to do, no authentication needed */
;
}
else if (socksreq[1] == 2) {
/* Needs user name and password */
size_t userlen, pwlen;
int len;
if(proxy_name && proxy_password) {
userlen = strlen(proxy_name);
pwlen = proxy_password?strlen(proxy_password):0;
}
else {
userlen = 0;
pwlen = 0;
}
/* username/password request looks like
* +----+------+----------+------+----------+
* |VER | ULEN | UNAME | PLEN | PASSWD |
* +----+------+----------+------+----------+
* | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
* +----+------+----------+------+----------+
*/
len = 0;
socksreq[len++] = 1; /* username/pw subnegotiation version */
socksreq[len++] = (char) userlen;
memcpy(socksreq + len, proxy_name, (int) userlen);
len += userlen;
socksreq[len++] = (char) pwlen;
memcpy(socksreq + len, proxy_password, (int) pwlen);
len += pwlen;
code = Curl_write(conn, sock, (char *)socksreq, len, &written);
if ((code != CURLE_OK) || (len != written)) {
failf(data, "Failed to send SOCKS5 sub-negotiation request.");
return CURLE_COULDNT_CONNECT;
}
result=blockread_all(conn, sock, (char *)socksreq, 2, &actualread,
timeout);
if ((result != CURLE_OK) || (actualread != 2)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
return CURLE_COULDNT_CONNECT;
}
/* ignore the first (VER) byte */
if (socksreq[1] != 0) { /* status */
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
socksreq[0], socksreq[1]);
return CURLE_COULDNT_CONNECT;
}
/* Everything is good so far, user was authenticated! */
}
else {
/* error */
if (socksreq[1] == 1) {
failf(data,
"SOCKS5 GSSAPI per-message authentication is not supported.");
return CURLE_COULDNT_CONNECT;
}
else if (socksreq[1] == 255) {
if (!proxy_name || !*proxy_name) {
failf(data,
"No authentication method was acceptable. (It is quite likely"
" that the SOCKS5 server wanted a username/password, since none"
" was supplied to the server on this connection.)");
}
else {
failf(data, "No authentication method was acceptable.");
}
return CURLE_COULDNT_CONNECT;
}
else {
failf(data,
"Undocumented SOCKS5 mode attempted to be used by server.");
return CURLE_COULDNT_CONNECT;
}
}
/* Authentication is complete, now specify destination to the proxy */
socksreq[0] = 5; /* version (SOCKS5) */
socksreq[1] = 1; /* connect */
socksreq[2] = 0; /* must be zero */
socksreq[3] = 1; /* IPv4 = 1 */
{
struct Curl_dns_entry *dns;
Curl_addrinfo *hp=NULL;
int rc = Curl_resolv(conn, conn->host.name, (int)conn->remote_port, &dns);
if(rc == CURLRESOLV_ERROR)
return CURLE_COULDNT_RESOLVE_HOST;
if(rc == CURLRESOLV_PENDING)
/* this requires that we're in "wait for resolve" state */
rc = Curl_wait_for_resolv(conn, &dns);
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
* returns a Curl_addrinfo pointer that may not always look the same.
*/
if(dns)
hp=dns->addr;
if (hp) {
char buf[64];
unsigned short ip[4];
Curl_printable_address(hp, buf, sizeof(buf));
if(4 == sscanf( buf, "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3])) {
socksreq[4] = (unsigned char)ip[0];
socksreq[5] = (unsigned char)ip[1];
socksreq[6] = (unsigned char)ip[2];
socksreq[7] = (unsigned char)ip[3];
}
else
hp = NULL; /* fail! */
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
conn->host.name);
return CURLE_COULDNT_RESOLVE_HOST;
}
}
*((unsigned short*)&socksreq[8]) = htons(conn->remote_port);
{
const int packetsize = 10;
code = Curl_write(conn, sock, (char *)socksreq, packetsize, &written);
if ((code != CURLE_OK) || (written != packetsize)) {
failf(data, "Failed to send SOCKS5 connect request.");
return CURLE_COULDNT_CONNECT;
}
result = blockread_all(conn, sock, (char *)socksreq, packetsize,
&actualread, timeout);
if ((result != CURLE_OK) || (actualread != packetsize)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
if (socksreq[0] != 5) { /* version */
failf(data,
"SOCKS5 reply has wrong version, version should be 5.");
return CURLE_COULDNT_CONNECT;
}
if (socksreq[1] != 0) { /* Anything besides 0 is an error */
failf(data,
"Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(unsigned int)ntohs(*(unsigned short*)(&socksreq[8])),
socksreq[1]);
return CURLE_COULDNT_CONNECT;
}
}
Curl_nonblock(sock, TRUE);
return CURLE_OK; /* Proxy was successful! */
}

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