ENH: Update Curl to 7.12.1

This commit is contained in:
Andy Cedilnik 2004-10-05 09:34:20 -04:00
parent 50da032847
commit 609801fe67
114 changed files with 19972 additions and 8911 deletions

View File

@ -1,58 +0,0 @@
#
# Check if the symbol exists in include files
#
# CHECK_SYMBOL_EXISTS - macro which checks the symbol exists in include files.
# SYMBOL - symbol
# FILES - include files to check
# VARIABLE - variable to return result
#
MACRO(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE)
IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
SET(CHECK_SYMBOL_EXISTS_CONTENT "/* */\n")
SET(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS})
STRING(ASCII 35 POUND)
STRING(ASCII 40 OPEN_PARENT)
STRING(ASCII 41 CLOSE_PARENT)
SET(PARENTS "${OPEN_PARENT}${CLOSE_PARENT}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_SYMBOL_EXISTS_LIBS
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ENDIF(CMAKE_REQUIRED_LIBRARIES)
FOREACH(FILE ${FILES})
SET(CHECK_SYMBOL_EXISTS_CONTENT
"${CHECK_SYMBOL_EXISTS_CONTENT}${POUND}include <${FILE}>\n")
ENDFOREACH(FILE)
SET(CHECK_SYMBOL_EXISTS_CONTENT
"${CHECK_SYMBOL_EXISTS_CONTENT}\nvoid cmakeRequireSymbol${OPEN_PARENT}int dummy,...${CLOSE_PARENT}{${OPEN_PARENT}void${CLOSE_PARENT}dummy;}\nint main${PARENTS}\n{\n${POUND}ifndef ${SYMBOL}\n cmakeRequireSymbol${OPEN_PARENT}0,&${SYMBOL}${CLOSE_PARENT};\n${POUND}endif\n return 0;\n}\n")
WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c
"${CHECK_SYMBOL_EXISTS_CONTENT}")
MESSAGE(STATUS "Looking for ${SYMBOL}")
TRY_COMPILE(${VARIABLE}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c
CMAKE_FLAGS
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS}
"${CHECK_SYMBOL_EXISTS_LIBS}"
OUTPUT_VARIABLE OUTPUT)
IF(${VARIABLE})
MESSAGE(STATUS "Looking for ${SYMBOL} - found")
SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL}")
WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeOutput.log
"Determining if the ${SYMBOL} "
"exist passed with the following output:\n"
"${OUTPUT}\nFile ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c:\n"
"${CHECK_SYMBOL_EXISTS_CONTENT}" APPEND)
ELSE(${VARIABLE})
MESSAGE(STATUS "Looking for ${SYMBOL} - not found.")
SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL}")
WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeError.log
"Determining if the ${SYMBOL} "
"exist failed with the following output:\n"
"${OUTPUT}\nFile ${CMAKE_BINARY_DIR}/CMakeTmp/CheckSymbolExists.c:\n"
"${CHECK_SYMBOL_EXISTS_CONTENT}" APPEND)
ENDIF(${VARIABLE})
ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
ENDMACRO(CHECK_SYMBOL_EXISTS)

View File

@ -1,17 +1,18 @@
CMAKE_MINIMUM_REQUIRED(VERSION 1.5)
CMAKE_MINIMUM_REQUIRED(VERSION 2.0)
PROJECT(LIBCURL C)
INCLUDE_REGULAR_EXPRESSION("^.*\\.h$")
# Setup package meta-data
SET(PACKAGE "curl")
SET(VERSION "7.10.3")
SET(PACKAGE_TARNAME " ")
SET(VERSION "7.12.1")
SET(PACKAGE_TARNAME "curl")
SET(PACKAGE_BUGREPORT " ")
SET(PACKAGE_NAME " ")
SET(PACKAGE_VERSION " ")
SET(PACKAGE_STRING " ")
SET(OPERATING_SYSTEM ${CMAKE_SYSTEM_NAME})
SET(PACKAGE_NAME "curl")
SET(PACKAGE_VERSION "-")
SET(PACKAGE_STRING "curl-")
SET(PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/")
SET(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
# We need ansi c-flags, especially on HP
SET(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
@ -23,60 +24,79 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES AIX)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES AIX)
# Include all the necessary files for macros
INCLUDE (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake)
INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFiles.cmake)
INCLUDE (${CMAKE_ROOT}/Modules/CheckLibraryExists.cmake)
INCLUDE (${LIBCURL_SOURCE_DIR}/CMake/CheckSymbolExists.cmake)
INCLUDE (${CMAKE_ROOT}/Modules/CheckTypeSize.cmake)
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
INCLUDE (CheckFunctionExists)
INCLUDE (CheckIncludeFile)
INCLUDE (CheckIncludeFiles)
INCLUDE (CheckLibraryExists)
INCLUDE (CheckSymbolExists)
INCLUDE (CheckTypeSize)
SET(libCurl_SRCS
file.c
timeval.c
base64.c
hostip.c
progress.c
formdata.c
cookie.c
http.c
sendf.c
ftp.c
url.c
dict.c
if2ip.c
speedcheck.c
getdate.c
ldap.c
ssluse.c
version.c
getenv.c
escape.c
mprintf.c
telnet.c
getpass.c
netrc.c
getinfo.c
transfer.c
strequal.c
easy.c
http_chunks.c
connect.c
llist.c
content_encoding.c
cookie.c
dict.c
easy.c
escape.c
file.c
formdata.c
ftp.c
getdate.c
getenv.c
getinfo.c
hash.c
hostares.c
hostasyn.c
hostip.c
hostip4.c
hostip6.c
hostsyn.c
hostthre.c
http.c
http_chunks.c
http_digest.c
http_negotiate.c
http_ntlm.c
if2ip.c
inet_ntop.c
inet_pton.c
krb4.c
ldap.c
llist.c
md5.c
memdebug.c
mprintf.c
multi.c
netrc.c
progress.c
security.c
sendf.c
share.c
speedcheck.c
ssluse.c
strequal.c
strerror.c
strtok.c
strtoofft.c
telnet.c
timeval.c
transfer.c
url.c
version.c
)
# if we have Kerberos 4, right now this is never on
IF(KRB4)
#OPTION(CURL_KRB4 "Use Kerberos 4" OFF)
IF(CURL_KRB4)
SET(libCurl_SRCS ${libCurl_SRCS}
krb4.c
security.c
)
ENDIF(KRB4)
ENDIF(CURL_KRB4)
OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
#OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
MARK_AS_ADVANCED(CURL_MALLOC_DEBUG)
IF(CURL_MALLOC_DEBUG)
SET(libCurl_SRCS ${libCurl_SRCS}
@ -84,7 +104,6 @@ IF(CURL_MALLOC_DEBUG)
)
ENDIF(CURL_MALLOC_DEBUG)
# On windows preload settings
IF(WIN32)
INCLUDE(${LIBCURL_SOURCE_DIR}/Platforms/WindowsCache.cmake)
@ -114,9 +133,11 @@ ENDIF(NOT NOT_NEED_LIBNSL)
CHECK_LIBRARY_EXISTS_CONCAT("ws2_32" getch HAVE_LIBWS2_32)
CHECK_LIBRARY_EXISTS_CONCAT("winmm" getch HAVE_LIBWINMM)
CHECK_LIBRARY_EXISTS_CONCAT("z" inflateEnd HAVE_LIBZ)
CHECK_LIBRARY_EXISTS_CONCAT("crypto" CRYPTO_lock HAVE_LIBCRYPTO)
#OPTION(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" OFF)
MARK_AS_ADVANCED(CMAKE_USE_OPENSSL)
IF(CMAKE_USE_OPENSSL)
CHECK_LIBRARY_EXISTS_CONCAT("crypto" CRYPTO_lock HAVE_LIBCRYPTO)
CHECK_LIBRARY_EXISTS_CONCAT("ssl" SSL_connect HAVE_LIBSSL)
ENDIF(CMAKE_USE_OPENSSL)
@ -155,6 +176,8 @@ MACRO(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
ENDMACRO(CHECK_INCLUDE_FILE_CONCAT)
# Check for header files
CHECK_INCLUDE_FILE_CONCAT("stdio.h" HAVE_STDIO_H)
CHECK_INCLUDE_FILE_CONCAT("stddef.h" HAVE_STDDEF_H)
CHECK_INCLUDE_FILE_CONCAT("sys/types.h" HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILE_CONCAT("inttypes.h" HAVE_INTTYPES_H)
CHECK_INCLUDE_FILE_CONCAT("alloca.h" HAVE_ALLOCA_H)
@ -164,8 +187,9 @@ CHECK_INCLUDE_FILE_CONCAT("fcntl.h" HAVE_FCNTL_H)
CHECK_INCLUDE_FILE_CONCAT("malloc.h" HAVE_MALLOC_H)
CHECK_INCLUDE_FILE_CONCAT("memory.h" HAVE_MEMORY_H)
CHECK_INCLUDE_FILE_CONCAT("netdb.h" HAVE_NETDB_H)
CHECK_INCLUDE_FILE_CONCAT("zlib.h" HAVE_ZLIB_H)
CHECK_INCLUDE_FILE_CONCAT("sys/poll.h" HAVE_SYS_POLL_H)
CHECK_INCLUDE_FILE_CONCAT("assert.h" HAVE_ASSERT_H)
CHECK_INCLUDE_FILE_CONCAT("limits.h" HAVE_LIMITS_H)
IF(CMAKE_USE_OPENSSL)
CHECK_INCLUDE_FILE_CONCAT("openssl/x509.h" HAVE_OPENSSL_X509_H)
@ -175,13 +199,17 @@ IF(CMAKE_USE_OPENSSL)
CHECK_INCLUDE_FILE_CONCAT("openssl/pem.h" HAVE_OPENSSL_PEM_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/ssl.h" HAVE_OPENSSL_SSL_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/err.h" HAVE_OPENSSL_ERR_H)
CHECK_INCLUDE_FILE_CONCAT("openssl/rand.h" HAVE_OPENSSL_RAND_H)
ENDIF(CMAKE_USE_OPENSSL)
CHECK_INCLUDE_FILE_CONCAT("zlib.h" HAVE_ZLIB_H)
CHECK_INCLUDE_FILE_CONCAT("sys/socket.h" HAVE_SYS_SOCKET_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/in.h" HAVE_NETINET_IN_H)
CHECK_INCLUDE_FILE_CONCAT("net/if.h" HAVE_NET_IF_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/if_ether.h"
HAVE_NETINET_IF_ETHER_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/tcp.h"
HAVE_NETINET_TCP_H)
CHECK_INCLUDE_FILE_CONCAT("sys/select.h" HAVE_SYS_SELECT_H)
CHECK_INCLUDE_FILE_CONCAT("utime.h" HAVE_UTIME_H)
CHECK_INCLUDE_FILE_CONCAT("netinet/in.h" HAVE_NETINET_IN_H)
@ -206,12 +234,19 @@ CHECK_INCLUDE_FILE_CONCAT("sys/sockio.h" HAVE_SYS_SOCKIO_H)
CHECK_INCLUDE_FILE_CONCAT("x509.h" HAVE_X509_H)
CHECK_INCLUDE_FILE_CONCAT("setjmp.h" HAVE_SETJMP_H)
CHECK_INCLUDE_FILE_CONCAT("signal.h" HAVE_SIGNAL_H)
CHECK_INCLUDE_FILE_CONCAT("sys/ioctl.h" HAVE_SYS_IOCTL_H)
CHECK_INCLUDE_FILE_CONCAT("sys/utsname.h" HAVE_SYS_UTSNAME_H)
CHECK_TYPE_SIZE(size_t SIZEOF_SIZE_T)
CHECK_TYPE_SIZE(ssize_t SIZEOF_SSIZE_T)
CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
CHECK_TYPE_SIZE("long double" SIZEOF_LONG_DOUBLE)
IF(NOT HAVE_SIZEOF_SSIZE_T)
SET(ssize_t int)
ENDIF(NOT HAVE_SIZEOF_SSIZE_T)
IF(HAVE_SIZEOF_LONG_LONG)
SET(HAVE_LONGLONG 1)
ENDIF(HAVE_SIZEOF_LONG_LONG)
FIND_FILE(RANDOM_FILE urandom /dev)
MARK_AS_ADVANCED(RANDOM_FILE)
@ -231,6 +266,7 @@ CHECK_SYMBOL_EXISTS(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI)
CHECK_SYMBOL_EXISTS(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
CHECK_SYMBOL_EXISTS(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
CHECK_SYMBOL_EXISTS(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR)
CHECK_SYMBOL_EXISTS(inet_pton "${CURL_INCLUDES}" HAVE_INET_PTON)
CHECK_SYMBOL_EXISTS(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA)
CHECK_SYMBOL_EXISTS(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
CHECK_SYMBOL_EXISTS(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR)
@ -244,20 +280,30 @@ CHECK_SYMBOL_EXISTS(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT)
CHECK_SYMBOL_EXISTS(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
CHECK_SYMBOL_EXISTS(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
CHECK_SYMBOL_EXISTS(utime "${CURL_INCLUDES}" HAVE_UTIME)
CHECK_SYMBOL_EXISTS(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
CHECK_SYMBOL_EXISTS(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
CHECK_SYMBOL_EXISTS(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
IF(CMAKE_USE_OPENSSL)
CHECK_SYMBOL_EXISTS(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
CHECK_SYMBOL_EXISTS(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
CHECK_SYMBOL_EXISTS(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
CHECK_SYMBOL_EXISTS(CRYPTO_cleanup_all_ex_data "${CURL_INCLUDES}"
HAVE_CRYPTO_CLEANUP_ALL_EX_DATA)
ENDIF(CMAKE_USE_OPENSSL)
CHECK_SYMBOL_EXISTS(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
CHECK_SYMBOL_EXISTS(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
CHECK_SYMBOL_EXISTS(gethostbyname_r "${CURL_INCLUDES};netdb.h" HAVE_GETHOSTBYNAME_R)
CHECK_SYMBOL_EXISTS(gethostbyaddr_r "${CURL_INCLUDES};netdb.h" HAVE_GETHOSTBYADDR_R)
CHECK_SYMBOL_EXISTS(gethostbyname "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME)
CHECK_SYMBOL_EXISTS(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
CHECK_SYMBOL_EXISTS(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
CHECK_SYMBOL_EXISTS(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
CHECK_SYMBOL_EXISTS(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
IF(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
SET(HAVE_SIGNAL 1)
ENDIF(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
CHECK_SYMBOL_EXISTS(uname "${CURL_INCLUDES}" HAVE_UNAME)
CHECK_SYMBOL_EXISTS(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
CHECK_SYMBOL_EXISTS(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R)
CHECK_SYMBOL_EXISTS(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
CHECK_SYMBOL_EXISTS(perror "${CURL_INCLUDES}" HAVE_PERROR)
# only build compat strtok if we need to
IF (NOT HAVE_STRTOK_R)
@ -334,6 +380,7 @@ FOREACH(CURL_TEST
HAVE_INET_NTOA_R_DECL
HAVE_INET_NTOA_R_DECL_REENTRANT
HAVE_GETADDRINFO
_FILE_OFFSET_BITS
)
CURL_INTERNAL_TEST(${CURL_TEST})
ENDFOREACH(CURL_TEST)
@ -398,21 +445,34 @@ IF(HAVE_LIBZ)
SET(libCurl_SRCS ${libCurl_SRCS} content_encoding.c)
ENDIF(HAVE_LIBZ)
# Check for nonblocking
IF(_FILE_OFFSET_BITS)
SET(_FILE_OFFSET_BITS 64)
ENDIF(_FILE_OFFSET_BITS)
SET(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
SET(CMAKE_EXTRA_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/curl/curl.h")
CHECK_TYPE_SIZE("curl_off_t" SIZEOF_CURL_OFF_T)
SET(CMAKE_EXTRA_INCLUDE_FILES)
SET(CMAKE_REQUIRED_FLAGS)
SET(HAVE_SOME_NONBLOCK 0)
FOREACH(CURL_TEST
HAVE_FIONBIO
HAVE_IOCTLSOCKET
HAVE_IOCTLSOCKET_CASE
HAVE_O_NONBLOCK)
IF(${CURL_TEST})
SET(HAVE_SOME_NONBLOCK 1)
ENDIF(${CURL_TEST})
ENDFOREACH(CURL_TEST)
IF(NOT HAVE_SOME_NONBLOCK)
SET(HAVE_DISABLED_NONBLOCKING 1)
ENDIF(NOT HAVE_SOME_NONBLOCK)
# Check for nonblocking
#OPTION(CURL_HAVE_DISABLED_NONBLOCKING "Disable non-blocking socket detection" OFF)
SET(HAVE_DISABLED_NONBLOCKING)
IF(CURL_HAVE_DISABLED_NONBLOCKING)
SET(HAVE_SOME_NONBLOCK 0)
FOREACH(CURL_TEST
HAVE_FIONBIO
HAVE_IOCTLSOCKET
HAVE_IOCTLSOCKET_CASE
HAVE_O_NONBLOCK)
IF(${CURL_TEST})
SET(HAVE_SOME_NONBLOCK 1)
ENDIF(${CURL_TEST})
ENDFOREACH(CURL_TEST)
IF(NOT HAVE_SOME_NONBLOCK)
SET(HAVE_DISABLED_NONBLOCKING 1)
ENDIF(NOT HAVE_SOME_NONBLOCK)
ENDIF(CURL_HAVE_DISABLED_NONBLOCKING)
IF(RETSIGTYPE_TEST)
SET(RETSIGTYPE void)

View File

@ -0,0 +1,49 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "amigaos.h"
#include <stdio.h> /* for stderr */
struct Library *SocketBase = NULL;
void amiga_cleanup()
{
if(SocketBase)
CloseLibrary(SocketBase);
SocketBase = NULL;
}
BOOL amiga_init()
{
if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) {
fprintf(stderr, "No TCP/IP Stack running!\n\a");
return FALSE;
}
atexit(amiga_cleanup);
return TRUE;
}

View File

@ -0,0 +1,52 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#ifndef LIBCURL_AMIGAOS_H
#define LIBCURL_AMIGAOS_H
#ifndef __ixemul__
#include <exec/types.h>
#include <exec/execbase.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <bsdsocket.h>
#include "config-amigaos.h"
#define select(args...) WaitSelect( args, NULL)
#define inet_ntoa(x) Inet_NtoA( x ## .s_addr)
#define ioctl(a,b,c,d) IoctlSocket( (LONG)a, (ULONG)b, (char*)c)
#define _AMIGASF 1
extern void amiga_cleanup();
extern BOOL amiga_init();
#else /* __ixemul__ */
#warning compiling with ixemul...
#endif /* __ixemul__ */
#endif /* LIBCURL_AMIGAOS_H */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -26,15 +26,15 @@
/*
* Telnet option defines. Add more here if in need.
*/
#define TELOPT_BINARY 0 /* binary 8bit data */
#define TELOPT_SGA 3 /* Supress Go Ahead */
#define TELOPT_EXOPL 255 /* EXtended OPtions List */
#define TELOPT_TTYPE 24 /* Terminal TYPE */
#define TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
#define CURL_TELOPT_BINARY 0 /* binary 8bit data */
#define CURL_TELOPT_SGA 3 /* Supress Go Ahead */
#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */
#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */
#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */
#define TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */
#define NEW_ENV_VAR 0
#define NEW_ENV_VALUE 1
#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */
#define CURL_NEW_ENV_VAR 0
#define CURL_NEW_ENV_VALUE 1
/*
* The telnet options represented as strings
@ -53,31 +53,27 @@ static const char *telnetoptions[]=
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
#define TELOPT_MAXIMUM TELOPT_NEW_ENVIRON
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
#define TELOPT_OK(x) ((x) <= TELOPT_MAXIMUM)
#define TELOPT(x) telnetoptions[x]
#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
#define CURL_TELOPT(x) telnetoptions[x]
#define NTELOPTS 40
#ifdef SE
# undef SE
#endif
#define CURL_NTELOPTS 40
/*
* First some defines
*/
#define xEOF 236 /* End Of File */
#define SE 240 /* Sub negotiation End */
#define NOP 241 /* No OPeration */
#define DM 242 /* Data Mark */
#define GA 249 /* Go Ahead, reverse the line */
#define SB 250 /* SuBnegotiation */
#define WILL 251 /* Our side WILL use this option */
#define WONT 252 /* Our side WON'T use this option */
#define DO 253 /* DO use this option! */
#define DONT 254 /* DON'T use this option! */
#define IAC 255 /* Interpret As Command */
#define CURL_xEOF 236 /* End Of File */
#define CURL_SE 240 /* Sub negotiation End */
#define CURL_NOP 241 /* No OPeration */
#define CURL_DM 242 /* Data Mark */
#define CURL_GA 249 /* Go Ahead, reverse the line */
#define CURL_SB 250 /* SuBnegotiation */
#define CURL_WILL 251 /* Our side WILL use this option */
#define CURL_WONT 252 /* Our side WON'T use this option */
#define CURL_DO 253 /* DO use this option! */
#define CURL_DONT 254 /* DON'T use this option! */
#define CURL_IAC 255 /* Interpret As Command */
/*
* Then those numbers represented as strings:
@ -90,16 +86,16 @@ static const char *telnetcmds[]=
"WILL", "WONT", "DO", "DONT", "IAC"
};
#define TELCMD_MINIMUM xEOF /* the first one */
#define TELCMD_MAXIMUM IAC /* surprise, 255 is the last one! ;-) */
#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */
#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */
#define TELQUAL_IS 0
#define TELQUAL_SEND 1
#define TELQUAL_INFO 2
#define TELQUAL_NAME 3
#define CURL_TELQUAL_IS 0
#define CURL_TELQUAL_SEND 1
#define CURL_TELQUAL_INFO 2
#define CURL_TELQUAL_NAME 3
#define TELCMD_OK(x) ( ((unsigned int)(x) >= TELCMD_MINIMUM) && \
((unsigned int)(x) <= TELCMD_MAXIMUM) )
#define TELCMD(x) telnetcmds[(x)-TELCMD_MINIMUM]
#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
#endif
#endif

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -28,7 +28,7 @@
* a base64-encoded version to stdout, and the length returned by the
* encoding function to stderr. Compile with -DTEST_DECODE for a program that
* will go the other way.
*
*
* This code will break if int is smaller than 32 bits
*/
@ -41,12 +41,13 @@
#include <curl/mprintf.h>
#include "base64.h"
#include "memory.h"
#ifdef MALLOCDEBUG
/* include memdebug.h last */
#include "memdebug.h"
#endif
static void decodeQuantum(unsigned char *dest, char *src)
static void decodeQuantum(unsigned char *dest, const char *src)
{
unsigned int x = 0;
int i;
@ -55,7 +56,7 @@ static void decodeQuantum(unsigned char *dest, char *src)
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')
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;
@ -65,48 +66,53 @@ static void decodeQuantum(unsigned char *dest, char *src)
x = (x << 6);
}
dest[2] = (unsigned char)(x & 255); x >>= 8;
dest[1] = (unsigned char)(x & 255); x >>= 8;
dest[0] = (unsigned char)(x & 255); x >>= 8;
dest[2] = (unsigned char)(x & 255);
x >>= 8;
dest[1] = (unsigned char)(x & 255);
x >>= 8;
dest[0] = (unsigned char)(x & 255);
}
/* base64Decode
* Given a base64 string at src, decode it into the memory pointed
* to by dest. If rawLength points to a valid address (ie not NULL),
* store the length of the decoded data to it.
/*
* 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.
*/
static void base64Decode(unsigned char *dest, char *src, int *rawLength)
size_t Curl_base64_decode(const char *src, char *dest)
{
int length = 0;
int equalsTerm = 0;
int i;
int numQuantums;
unsigned char lastQuantum[3];
size_t rawlen=0;
while((src[length] != '=') && src[length])
length++;
while(src[length+equalsTerm] == '=')
equalsTerm++;
numQuantums = (length + equalsTerm) / 4;
if(rawLength)
*rawLength = (numQuantums * 3) - equalsTerm;
rawlen = (numQuantums * 3) - equalsTerm;
for(i = 0; i < numQuantums - 1; i++) {
decodeQuantum(dest, src);
decodeQuantum((unsigned char *)dest, src);
dest += 3; src += 4;
}
decodeQuantum(lastQuantum, src);
for(i = 0; i < 3 - equalsTerm; i++)
dest[i] = lastQuantum[i];
return rawlen;
}
/* ---- Base64 Encoding --- */
static char table64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
* Curl_base64_encode()
*
@ -115,7 +121,7 @@ static char table64[]=
* went wrong, -1 is returned.
*
*/
int Curl_base64_encode(const void *inp, int insize, char **outptr)
size_t Curl_base64_encode(const char *inp, size_t insize, char **outptr)
{
unsigned char ibuf[3];
unsigned char obuf[4];
@ -126,16 +132,18 @@ int Curl_base64_encode(const void *inp, int insize, char **outptr)
char *indata = (char *)inp;
*outptr = NULL; /* set to NULL in case of failure before we reach the end */
if(0 == insize)
insize = (int)strlen(indata);
insize = strlen(indata);
base64data = output = (char*)malloc(insize*4/3+4);
if(NULL == output)
return -1;
return 0;
while(insize > 0) {
for (i = inputparts = 0; i < 3; i++) {
if(*indata) {
for (i = inputparts = 0; i < 3; i++) {
if(insize > 0) {
inputparts++;
ibuf[i] = *indata;
indata++;
@ -144,32 +152,30 @@ int Curl_base64_encode(const void *inp, int insize, char **outptr)
else
ibuf[i] = 0;
}
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);
obuf [0] = (ibuf [0] & 0xFC) >> 2;
obuf [1] = ((ibuf [0] & 0x03) << 4) | ((ibuf [1] & 0xF0) >> 4);
obuf [2] = ((ibuf [1] & 0x0F) << 2) | ((ibuf [2] & 0xC0) >> 6);
obuf [3] = ibuf [2] & 0x3F;
switch(inputparts) {
case 1: /* only one byte read */
sprintf(output, "%c%c==",
table64[obuf[0]],
table64[obuf[1]]);
snprintf(output, 5, "%c%c==",
table64[obuf[0]],
table64[obuf[1]]);
break;
case 2: /* two bytes read */
sprintf(output, "%c%c%c=",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]]);
snprintf(output, 5, "%c%c%c=",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]]);
break;
default:
sprintf(output, "%c%c%c%c",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
table64[obuf[3]] );
snprintf(output, 5, "%c%c%c%c",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
table64[obuf[3]] );
break;
}
output += 4;
@ -177,18 +183,10 @@ int Curl_base64_encode(const void *inp, int insize, char **outptr)
*output=0;
*outptr = base64data; /* make it return the actual data memory */
return (int)strlen(base64data); /* return the length of the new data */
return strlen(base64data); /* return the length of the new data */
}
/* ---- End of Base64 Encoding ---- */
int Curl_base64_decode(const char *str, void *data)
{
int ret;
base64Decode((unsigned char *)data, (char *)str, &ret);
return ret;
}
/************* TEST HARNESS STUFF ****************/
@ -204,24 +202,26 @@ void *suck(int *);
int main(int argc, char **argv, char **envp)
{
char *base64;
int base64Len;
size_t base64Len;
unsigned char *data;
int dataLen;
data = (unsigned char *)suck(&dataLen);
base64Len = Curl_base64_encode(data, dataLen, &base64);
fprintf(stderr, "%d\n", base64Len);
fprintf(stdout, "%s", base64);
free(base64); free(data);
return 0;
}
#endif
#ifdef TEST_DECODE
/* decoding test harness. Read in a base64 string from stdin and write out the
/* decoding test harness. Read in a base64 string from stdin and write out the
* length returned by Curl_base64_decode, followed by the decoded data itself
*
* gcc -DTEST_DECODE base64.c -o base64 mprintf.o memdebug.o
*/
#include <stdio.h>
@ -234,14 +234,32 @@ int main(int argc, char **argv, char **envp)
int base64Len;
unsigned char *data;
int dataLen;
int i, j;
base64 = (char *)suck(&base64Len);
data = (unsigned char *)malloc(base64Len * 3/4 + 8);
dataLen = Curl_base64_decode(base64, data);
fprintf(stderr, "%d\n", dataLen);
fwrite(data,1,dataLen,stdout);
for(i=0; i < dataLen; i+=0x10) {
printf("0x%02x: ", i);
for(j=0; j < 0x10; j++)
if((j+i) < dataLen)
printf("%02x ", data[i+j]);
else
printf(" ");
printf(" | ");
for(j=0; j < 0x10; j++)
if((j+i) < dataLen)
printf("%c", isgraph(data[i+j])?data[i+j]:'.');
else
break;
puts("");
}
free(base64); free(data);
return 0;
}
@ -255,7 +273,7 @@ void *suck(int *lenptr)
unsigned char *buf = NULL;
int lastread;
int len = 0;
do {
cursize *= 2;
buf = (unsigned char *)realloc(buf, cursize);
@ -263,16 +281,8 @@ void *suck(int *lenptr)
lastread = fread(buf + len, 1, cursize - len, stdin);
len += lastread;
} while(!feof(stdin));
lenptr[0] = len;
return (void *)buf;
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -22,6 +22,6 @@
*
* $Id$
***************************************************************************/
int Curl_base64_encode(const void *data, int size, char **str);
int Curl_base64_decode(const char *str, void *data);
size_t Curl_base64_encode(const char *input, size_t size, char **str);
size_t Curl_base64_decode(const char *source, char *dest);
#endif

View File

@ -1,31 +1 @@
#ifndef __CA_BUNDLE_H
#define __CA_BUNDLE_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
#ifndef CURL_CA_BUNDLE
/* Set this to the full path file name of the ca cert bundle */
#undef CURL_CA_BUNDLE
#endif
#endif /* __CA_BUNDLE_H */
/* ca bundle path set in here*/

View File

@ -1,427 +1,424 @@
/* lib/config.h.in. Generated from configure.in by autoheader. */
/* Name of this package! */
#cmakedefine PACKAGE "${PACKAGE}"
/* Version number of this archive. */
#cmakedefine VERSION "${VERSION}"
/* Define if you have the getpass function. */
#cmakedefine HAVE_GETPASS ${HAVE_GETPASS}
/* Define cpu-machine-OS */
#define OS "${OPERATING_SYSTEM}"
/* Define if you have the gethostbyaddr_r() function with 5 arguments */
#cmakedefine HAVE_GETHOSTBYADDR_R_5 ${HAVE_GETHOSTBYADDR_R_5}
/* Define if you have the gethostbyaddr_r() function with 7 arguments */
#cmakedefine HAVE_GETHOSTBYADDR_R_7 ${HAVE_GETHOSTBYADDR_R_7}
/* Define if you have the gethostbyaddr_r() function with 8 arguments */
#cmakedefine HAVE_GETHOSTBYADDR_R_8 ${HAVE_GETHOSTBYADDR_R_8}
/* Define if you have the gethostbyname_r() function with 3 arguments */
#cmakedefine HAVE_GETHOSTBYNAME_R_3 ${HAVE_GETHOSTBYNAME_R_3}
/* Define if you have the gethostbyname_r() function with 5 arguments */
#cmakedefine HAVE_GETHOSTBYNAME_R_5 ${HAVE_GETHOSTBYNAME_R_5}
/* Define if you have the gethostbyname_r() function with 6 arguments */
#cmakedefine HAVE_GETHOSTBYNAME_R_6 ${HAVE_GETHOSTBYNAME_R_6}
/* Define if you have the inet_ntoa_r function declared. */
#cmakedefine HAVE_INET_NTOA_R_DECL ${HAVE_INET_NTOA_R_DECL}
/* Define if you need the _REENTRANT define for some functions */
#cmakedefine NEED_REENTRANT ${NEED_REENTRANT}
/* Define if you have the Kerberos4 libraries (including -ldes) */
#cmakedefine KRB4 ${KRB4}
/* Define if you want to enable IPv6 support */
#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6}
/* Define this to 'int' if ssize_t is not an available typedefed type */
#cmakedefine ssize_t ${ssize_t}
/* Define this to 'int' if socklen_t is not an available typedefed type */
#cmakedefine socklen_t ${socklen_t}
/* Define this as a suitable file to read random data from */
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
/* Define this to your Entropy Gathering Daemon socket pathname */
#cmakedefine EGD_SOCKET ${EGD_SOCKET}
/* Define if you have a working OpenSSL installation */
#cmakedefine OPENSSL_ENABLED ${OPENSSL_ENABLED}
/* Define the one correct non-blocking socket method below */
#cmakedefine HAVE_FIONBIO ${HAVE_FIONBIO}
#cmakedefine HAVE_IOCTLSOCKET ${HAVE_IOCTLSOCKET}
#cmakedefine HAVE_IOCTLSOCKET_CASE ${HAVE_IOCTLSOCKET_CASE}
#cmakedefine HAVE_O_NONBLOCK ${HAVE_O_NONBLOCK}
#cmakedefine HAVE_DISABLED_NONBLOCKING ${HAVE_DISABLED_NONBLOCKING}
/* Define this to 'int' if in_addr_t is not an available typedefed type */
#cmakedefine in_addr_t ${in_addr_t}
/* Define to disable DICT */
#cmakedefine CURL_DISABLE_DICT ${CURL_DISABLE_DICT}
/* Define to disable FILE */
#cmakedefine CURL_DISABLE_FILE ${CURL_DISABLE_FILE}
/* Define to disable FTP */
#cmakedefine CURL_DISABLE_FTP ${CURL_DISABLE_FTP}
/* Define to disable GOPHER */
#cmakedefine CURL_DISABLE_GOPHER ${CURL_DISABLE_GOPHER}
/* Define to disable HTTP */
#cmakedefine CURL_DISABLE_HTTP ${CURL_DISABLE_HTTP}
/* Define to disable LDAP */
#cmakedefine CURL_DISABLE_LDAP ${CURL_DISABLE_LDAP}
/* Define to disable TELNET */
#cmakedefine CURL_DISABLE_TELNET ${CURL_DISABLE_TELNET}
/* Define if you have zlib present */
#cmakedefine HAVE_LIBZ ${HAVE_LIBZ}
/* CA bundle full path name */
#cmakedefine CURL_CA_BUNDLE ${CURL_CA_BUNDLE}
/* to disable DICT */
#cmakedefine CURL_DISABLE_DICT ${CURL_DISABLE_DICT}
/* to disable FILE */
#cmakedefine CURL_DISABLE_FILE ${CURL_DISABLE_FILE}
#cmakedefine CURL_DISABLE_FILE ${CURL_DISABLE_FILE}
/* to disable FTP */
#cmakedefine CURL_DISABLE_FTP ${CURL_DISABLE_FTP}
#cmakedefine CURL_DISABLE_FTP ${CURL_DISABLE_FTP}
/* to disable GOPHER */
#cmakedefine CURL_DISABLE_GOPHER ${CURL_DISABLE_GOPHER}
#cmakedefine CURL_DISABLE_GOPHER ${CURL_DISABLE_GOPHER}
/* to disable HTTP */
#cmakedefine CURL_DISABLE_HTTP ${CURL_DISABLE_HTTP}
#cmakedefine CURL_DISABLE_HTTP ${CURL_DISABLE_HTTP}
/* to disable LDAP */
#cmakedefine CURL_DISABLE_LDAP ${CURL_DISABLE_LDAP}
#cmakedefine CURL_DISABLE_LDAP ${CURL_DISABLE_LDAP}
/* to disable TELNET */
#cmakedefine CURL_DISABLE_TELNET ${CURL_DISABLE_TELNET}
#cmakedefine CURL_DISABLE_TELNET ${CURL_DISABLE_TELNET}
/* Set to explicitly specify we don't want to use thread-safe functions */
#cmakedefine DISABLED_THREADSAFE ${DISABLED_THREADSAFE}
#cmakedefine DISABLED_THREADSAFE ${DISABLED_THREADSAFE}
/* your Entropy Gathering Daemon socket pathname */
#cmakedefine EGD_SOCKET ${EGD_SOCKET}
#cmakedefine EGD_SOCKET ${EGD_SOCKET}
/* Define if you want to enable IPv6 support */
#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6}
#cmakedefine ENABLE_IPV6 ${ENABLE_IPV6}
/* Define to 1 if you have the <alloca.h> header file. */
#cmakedefine HAVE_ALLOCA_H ${HAVE_ALLOCA_H}
#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}
#cmakedefine HAVE_ARPA_INET_H ${HAVE_ARPA_INET_H}
/* Define to 1 if you have the <assert.h> header file. */
#cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H}
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET ${HAVE_CLOSESOCKET}
#cmakedefine HAVE_CLOSESOCKET ${HAVE_CLOSESOCKET}
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA ${HAVE_CRYPTO_CLEANUP_ALL_EX_DATA}
/* Define to 1 if you have the <crypto.h> header file. */
#cmakedefine HAVE_CRYPTO_H ${HAVE_CRYPTO_H}
#cmakedefine HAVE_CRYPTO_H ${HAVE_CRYPTO_H}
/* Define to 1 if you have the <des.h> header file. */
#cmakedefine HAVE_DES_H ${HAVE_DES_H}
#cmakedefine HAVE_DES_H ${HAVE_DES_H}
/* to disable NON-BLOCKING connections */
#cmakedefine HAVE_DISABLED_NONBLOCKING ${HAVE_DISABLED_NONBLOCKING}
/* disabled non-blocking sockets */
#cmakedefine HAVE_DISABLED_NONBLOCKING ${HAVE_DISABLED_NONBLOCKING}
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H}
#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H}
/* Define to 1 if you have the `dlopen' function. */
#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN}
#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN}
/* Define to 1 if you have the <err.h> header file. */
#cmakedefine HAVE_ERR_H ${HAVE_ERR_H}
#cmakedefine HAVE_ERR_H ${HAVE_ERR_H}
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H}
#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H}
/* use FIONBIO for non-blocking sockets */
#cmakedefine HAVE_FIONBIO ${HAVE_FIONBIO}
/* Define if getaddrinfo exists and works */
#cmakedefine HAVE_GETADDRINFO ${HAVE_GETADDRINFO}
#cmakedefine HAVE_GETADDRINFO ${HAVE_GETADDRINFO}
/* Define to 1 if you have the `geteuid' function. */
#cmakedefine HAVE_GETEUID ${HAVE_GETEUID}
#cmakedefine HAVE_GETEUID ${HAVE_GETEUID}
/* Define to 1 if you have the `gethostbyaddr' function. */
#cmakedefine HAVE_GETHOSTBYADDR ${HAVE_GETHOSTBYADDR}
#cmakedefine HAVE_GETHOSTBYADDR ${HAVE_GETHOSTBYADDR}
/* Define to 1 if you have the `gethostbyaddr_r' function. */
#cmakedefine HAVE_GETHOSTBYADDR_R ${HAVE_GETHOSTBYADDR_R}
/* If you have gethostbyname */
#cmakedefine HAVE_GETHOSTBYNAME ${HAVE_GETHOSTBYNAME}
/* Define to 1 if you have the `gethostbyname_r' function. */
#cmakedefine HAVE_GETHOSTBYNAME_R ${HAVE_GETHOSTBYNAME_R}
#cmakedefine HAVE_GETHOSTBYNAME_R ${HAVE_GETHOSTBYNAME_R}
/* gethostbyname_r() takes 3 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_3 ${HAVE_GETHOSTBYNAME_R_3}
/* gethostbyname_r() takes 5 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_5 ${HAVE_GETHOSTBYNAME_R_5}
/* gethostbyname_r() takes 6 args */
#cmakedefine HAVE_GETHOSTBYNAME_R_6 ${HAVE_GETHOSTBYNAME_R_6}
/* Define to 1 if you have the `getpass_r' function. */
#cmakedefine HAVE_GETPASS_R ${HAVE_GETPASS_R}
#cmakedefine HAVE_GETPASS_R ${HAVE_GETPASS_R}
/* Define to 1 if you have the `getpwuid' function. */
#cmakedefine HAVE_GETPWUID ${HAVE_GETPWUID}
#cmakedefine HAVE_GETPWUID ${HAVE_GETPWUID}
/* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY}
#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY}
/* we have a glibc-style strerror_r() */
#cmakedefine HAVE_GLIBC_STRERROR_R ${HAVE_GLIBC_STRERROR_R}
/* Define to 1 if you have the `gmtime_r' function. */
#cmakedefine HAVE_GMTIME_R ${HAVE_GMTIME_R}
#cmakedefine HAVE_GMTIME_R ${HAVE_GMTIME_R}
/* if you have the gssapi libraries */
#cmakedefine HAVE_GSSAPI ${HAVE_GSSAPI}
/* if you have the Heimdal gssapi libraries */
#cmakedefine HAVE_GSSHEIMDAL ${HAVE_GSSHEIMDAL}
/* if you have the MIT gssapi libraries */
#cmakedefine HAVE_GSSMIT ${HAVE_GSSMIT}
/* Define to 1 if you have the `idn_free' function. */
#cmakedefine HAVE_IDN_FREE ${HAVE_IDN_FREE}
/* Define to 1 if you have the <idn-free.h> header file. */
#cmakedefine HAVE_IDN_FREE_H ${HAVE_IDN_FREE_H}
/* Define to 1 if you have the `inet_addr' function. */
#cmakedefine HAVE_INET_ADDR ${HAVE_INET_ADDR}
#cmakedefine HAVE_INET_ADDR ${HAVE_INET_ADDR}
/* Define to 1 if you have the `inet_ntoa' function. */
#cmakedefine HAVE_INET_NTOA ${HAVE_INET_NTOA}
#cmakedefine HAVE_INET_NTOA ${HAVE_INET_NTOA}
/* Define to 1 if you have the `inet_ntoa_r' function. */
#cmakedefine HAVE_INET_NTOA_R ${HAVE_INET_NTOA_R}
#cmakedefine HAVE_INET_NTOA_R ${HAVE_INET_NTOA_R}
/* inet_ntoa_r() is declared */
#cmakedefine HAVE_INET_NTOA_R_DECL ${HAVE_INET_NTOA_R_DECL}
/* Define to 1 if you have the `inet_pton' function. */
#cmakedefine HAVE_INET_PTON ${HAVE_INET_PTON}
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H}
#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H}
/* use ioctlsocket() for non-blocking sockets */
#cmakedefine HAVE_IOCTLSOCKET ${HAVE_IOCTLSOCKET}
/* use Ioctlsocket() for non-blocking sockets */
#cmakedefine HAVE_IOCTLSOCKET_CASE ${HAVE_IOCTLSOCKET_CASE}
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H ${HAVE_IO_H}
/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM ${HAVE_KRB_GET_OUR_IP_FOR_REALM}
/* Define to 1 if you have the <krb.h> header file. */
#cmakedefine HAVE_KRB_H ${HAVE_KRB_H}
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#cmakedefine HAVE_LIBCRYPTO ${HAVE_LIBCRYPTO}
/* Define to 1 if you have the `dl' library (-ldl). */
#cmakedefine HAVE_LIBDL ${HAVE_LIBDL}
/* Define to 1 if you have the `nsl' library (-lnsl). */
#cmakedefine HAVE_LIBNSL ${HAVE_LIBNSL}
/* Define to 1 if you have the `resolv' library (-lresolv). */
#cmakedefine HAVE_LIBRESOLV ${HAVE_LIBRESOLV}
/* Define to 1 if you have the `resolve' library (-lresolve). */
#cmakedefine HAVE_LIBRESOLVE ${HAVE_LIBRESOLVE}
/* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET ${HAVE_LIBSOCKET}
/* Define to 1 if you have the `ssl' library (-lssl). */
#cmakedefine HAVE_LIBSSL ${HAVE_LIBSSL}
/* Define to 1 if you have the `ucb' library (-lucb). */
#cmakedefine HAVE_LIBUCB ${HAVE_LIBUCB}
/* If zlib is available */
#cmakedefine HAVE_LIBZ ${HAVE_LIBZ}
/* Define to 1 if you have the `localtime_r' function. */
#cmakedefine HAVE_LOCALTIME_R ${HAVE_LOCALTIME_R}
/* Define to 1 if you have the <malloc.h> header file. */
#cmakedefine HAVE_MALLOC_H ${HAVE_MALLOC_H}
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H}
/* Define to 1 if you have the <netdb.h> header file. */
#cmakedefine HAVE_NETDB_H ${HAVE_NETDB_H}
/* Define to 1 if you have the <netinet/if_ether.h> header file. */
#cmakedefine HAVE_NETINET_IF_ETHER_H ${HAVE_NETINET_IF_ETHER_H}
/* Define to 1 if you have the <netinet/in.h> header file. */
#cmakedefine HAVE_NETINET_IN_H ${HAVE_NETINET_IN_H}
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H ${HAVE_NET_IF_H}
/* Define to 1 if you have the <openssl/crypto.h> header file. */
#cmakedefine HAVE_OPENSSL_CRYPTO_H ${HAVE_OPENSSL_CRYPTO_H}
/* Define to 1 if you have the <openssl/engine.h> header file. */
#cmakedefine HAVE_OPENSSL_ENGINE_H ${HAVE_OPENSSL_ENGINE_H}
/* Define to 1 if you have the <openssl/err.h> header file. */
#cmakedefine HAVE_OPENSSL_ERR_H ${HAVE_OPENSSL_ERR_H}
/* Define to 1 if you have the <openssl/pem.h> header file. */
#cmakedefine HAVE_OPENSSL_PEM_H ${HAVE_OPENSSL_PEM_H}
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#cmakedefine HAVE_OPENSSL_RSA_H ${HAVE_OPENSSL_RSA_H}
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#cmakedefine HAVE_OPENSSL_SSL_H ${HAVE_OPENSSL_SSL_H}
/* Define to 1 if you have the <openssl/x509.h> header file. */
#cmakedefine HAVE_OPENSSL_X509_H ${HAVE_OPENSSL_X509_H}
/* Define to 1 if you have the <pem.h> header file. */
#cmakedefine HAVE_PEM_H ${HAVE_PEM_H}
/* Define to 1 if you have the `perror' function. */
#cmakedefine HAVE_PERROR ${HAVE_PERROR}
/* Define to 1 if you have the `poll' function. */
#cmakedefine HAVE_POLL ${HAVE_POLL}
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H ${HAVE_PWD_H}
/* Define to 1 if you have the `RAND_egd' function. */
#cmakedefine HAVE_RAND_EGD ${HAVE_RAND_EGD}
/* Define to 1 if you have the `RAND_screen' function. */
#cmakedefine HAVE_RAND_SCREEN ${HAVE_RAND_SCREEN}
/* Define to 1 if you have the `RAND_status' function. */
#cmakedefine HAVE_RAND_STATUS ${HAVE_RAND_STATUS}
/* Define to 1 if you have the <rsa.h> header file. */
#cmakedefine HAVE_RSA_H ${HAVE_RSA_H}
/* Define to 1 if you have the `select' function. */
#cmakedefine HAVE_SELECT ${HAVE_SELECT}
/* Define to 1 if you have the <setjmp.h> header file. */
#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H}
/* Define to 1 if you have the `setvbuf' function. */
#cmakedefine HAVE_SETVBUF ${HAVE_SETVBUF}
/* Define to 1 if you have the <sgtty.h> header file. */
#cmakedefine HAVE_SGTTY_H ${HAVE_SGTTY_H}
/* Define to 1 if you have the `sigaction' function. */
#cmakedefine HAVE_SIGACTION ${HAVE_SIGACTION}
/* Define to 1 if you have the `signal' function. */
#cmakedefine HAVE_SIGNAL ${HAVE_SIGNAL}
/* If you have sigsetjmp */
#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP}
/* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET ${HAVE_SOCKET}
/* Define to 1 if you have the <ssl.h> header file. */
#cmakedefine HAVE_SSL_H ${HAVE_SSL_H}
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H}
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H}
/* Define to 1 if you have the `strcasecmp' function. */
#cmakedefine HAVE_STRCASECMP ${HAVE_STRCASECMP}
/* Define to 1 if you have the `strcmpi' function. */
#cmakedefine HAVE_STRCMPI ${HAVE_STRCMPI}
/* Define to 1 if you have the `strdup' function. */
#cmakedefine HAVE_STRDUP ${HAVE_STRDUP}
/* Define to 1 if you have the `strftime' function. */
#cmakedefine HAVE_STRFTIME ${HAVE_STRFTIME}
/* Define to 1 if you have the `stricmp' function. */
#cmakedefine HAVE_STRICMP ${HAVE_STRICMP}
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H}
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H ${HAVE_STRING_H}
/* Define to 1 if you have the `strlcat' function. */
#cmakedefine HAVE_STRLCAT ${HAVE_STRLCAT}
/* Define to 1 if you have the `strlcpy' function. */
#cmakedefine HAVE_STRLCPY ${HAVE_STRLCPY}
/* Define to 1 if you have the `strstr' function. */
#cmakedefine HAVE_STRSTR ${HAVE_STRSTR}
/* Define to 1 if you have the `strtok_r' function. */
#cmakedefine HAVE_STRTOK_R ${HAVE_STRTOK_R}
/* Define to 1 if you have the <sys/param.h> header file. */
#cmakedefine HAVE_SYS_PARAM_H ${HAVE_SYS_PARAM_H}
/* Define to 1 if you have the <sys/poll.h> header file. */
#cmakedefine HAVE_SYS_POLL_H ${HAVE_SYS_POLL_H}
/* Define to 1 if you have the <sys/select.h> header file. */
#cmakedefine HAVE_SYS_SELECT_H ${HAVE_SYS_SELECT_H}
/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}
/* Define to 1 if you have the <sys/sockio.h> header file. */
#cmakedefine HAVE_SYS_SOCKIO_H ${HAVE_SYS_SOCKIO_H}
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H}
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H ${HAVE_SYS_TIME_H}
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H}
/* Define to 1 if you have the <sys/utime.h> header file. */
#cmakedefine HAVE_SYS_UTIME_H ${HAVE_SYS_UTIME_H}
/* Define to 1 if you have the `tcgetattr' function. */
#cmakedefine HAVE_TCGETATTR ${HAVE_TCGETATTR}
/* Define to 1 if you have the `tcsetattr' function. */
#cmakedefine HAVE_TCSETATTR ${HAVE_TCSETATTR}
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
/* Define to 1 if you have the <termio.h> header file. */
#cmakedefine HAVE_TERMIO_H ${HAVE_TERMIO_H}
/* Define to 1 if you have the <time.h> header file. */
#cmakedefine HAVE_TIME_H ${HAVE_TIME_H}
/* Define to 1 if you have the `uname' function. */
#cmakedefine HAVE_UNAME ${HAVE_UNAME}
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
/* Define to 1 if you have the `utime' function. */
#cmakedefine HAVE_UTIME ${HAVE_UTIME}
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H}
/* Define to 1 if you have the <winsock.h> header file. */
#cmakedefine HAVE_WINSOCK_H ${HAVE_WINSOCK_H}
/* Define 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}
#cmakedefine HAVE_IO_H ${HAVE_IO_H}
/* if you have the Kerberos4 libraries (including -ldes) */
#cmakedefine KRB4 ${KRB4}
#cmakedefine HAVE_KRB4 ${HAVE_KRB4}
/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM ${HAVE_KRB_GET_OUR_IP_FOR_REALM}
/* Define to 1 if you have the <krb.h> header file. */
#cmakedefine HAVE_KRB_H ${HAVE_KRB_H}
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#cmakedefine HAVE_LIBCRYPTO ${HAVE_LIBCRYPTO}
/* Define to 1 if you have the `dl' library (-ldl). */
#cmakedefine HAVE_LIBDL ${HAVE_LIBDL}
/* Define to 1 if you have the `idn' library (-lidn). */
#cmakedefine HAVE_LIBIDN ${HAVE_LIBIDN}
/* Define to 1 if you have the `resolv' library (-lresolv). */
#cmakedefine HAVE_LIBRESOLV ${HAVE_LIBRESOLV}
/* Define to 1 if you have the `resolve' library (-lresolve). */
#cmakedefine HAVE_LIBRESOLVE ${HAVE_LIBRESOLVE}
/* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET ${HAVE_LIBSOCKET}
/* Define to 1 if you have the `ssl' library (-lssl). */
#cmakedefine HAVE_LIBSSL ${HAVE_LIBSSL}
/* if zlib is available */
#cmakedefine HAVE_LIBZ ${HAVE_LIBZ}
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H}
/* Define to 1 if you have the `localtime_r' function. */
#cmakedefine HAVE_LOCALTIME_R ${HAVE_LOCALTIME_R}
/* if your compiler supports 'long long' */
#cmakedefine HAVE_LONGLONG ${HAVE_LONGLONG}
/* Define to 1 if you have the <malloc.h> header file. */
#cmakedefine HAVE_MALLOC_H ${HAVE_MALLOC_H}
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H}
/* Define to 1 if you have the <netdb.h> header file. */
#cmakedefine HAVE_NETDB_H ${HAVE_NETDB_H}
/* Define to 1 if you have the <netinet/in.h> header file. */
#cmakedefine HAVE_NETINET_IN_H ${HAVE_NETINET_IN_H}
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#cmakedefine HAVE_NETINET_TCP_H ${HAVE_NETINET_TCP_H}
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H ${HAVE_NET_IF_H}
/* Define if NI_WITHSCOPEID exists and works */
#cmakedefine HAVE_NI_WITHSCOPEID ${HAVE_NI_WITHSCOPEID}
/* we have no strerror_r() proto */
#cmakedefine HAVE_NO_STRERROR_R_DECL ${HAVE_NO_STRERROR_R_DECL}
/* Define to 1 if you have the <openssl/crypto.h> header file. */
#cmakedefine HAVE_OPENSSL_CRYPTO_H ${HAVE_OPENSSL_CRYPTO_H}
/* Define to 1 if you have the <openssl/engine.h> header file. */
#cmakedefine HAVE_OPENSSL_ENGINE_H ${HAVE_OPENSSL_ENGINE_H}
/* Define to 1 if you have the <openssl/err.h> header file. */
#cmakedefine HAVE_OPENSSL_ERR_H ${HAVE_OPENSSL_ERR_H}
/* Define to 1 if you have the <openssl/pem.h> header file. */
#cmakedefine HAVE_OPENSSL_PEM_H ${HAVE_OPENSSL_PEM_H}
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#cmakedefine HAVE_OPENSSL_RSA_H ${HAVE_OPENSSL_RSA_H}
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#cmakedefine HAVE_OPENSSL_SSL_H ${HAVE_OPENSSL_SSL_H}
/* Define to 1 if you have the <openssl/x509.h> header file. */
#cmakedefine HAVE_OPENSSL_X509_H ${HAVE_OPENSSL_X509_H}
/* use O_NONBLOCK for non-blocking sockets */
#cmakedefine HAVE_O_NONBLOCK ${HAVE_O_NONBLOCK}
/* Define to 1 if you have the <pem.h> header file. */
#cmakedefine HAVE_PEM_H ${HAVE_PEM_H}
/* Define to 1 if you have the `perror' function. */
#cmakedefine HAVE_PERROR ${HAVE_PERROR}
/* Define to 1 if you have the `poll' function. */
#cmakedefine HAVE_POLL ${HAVE_POLL}
/* If you have a fine poll */
#cmakedefine HAVE_POLL_FINE ${HAVE_POLL_FINE}
/* we have a POSIX-style strerror_r() */
#cmakedefine HAVE_POSIX_STRERROR_R ${HAVE_POSIX_STRERROR_R}
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H ${HAVE_PWD_H}
/* Define to 1 if you have the `RAND_egd' function. */
#cmakedefine HAVE_RAND_EGD ${HAVE_RAND_EGD}
/* Define to 1 if you have the `RAND_screen' function. */
#cmakedefine HAVE_RAND_SCREEN ${HAVE_RAND_SCREEN}
/* Define to 1 if you have the `RAND_status' function. */
#cmakedefine HAVE_RAND_STATUS ${HAVE_RAND_STATUS}
/* Define to 1 if you have the <rsa.h> header file. */
#cmakedefine HAVE_RSA_H ${HAVE_RSA_H}
/* Define to 1 if you have the `select' function. */
#cmakedefine HAVE_SELECT ${HAVE_SELECT}
/* Define to 1 if you have the <setjmp.h> header file. */
#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H}
/* Define to 1 if you have the <sgtty.h> header file. */
#cmakedefine HAVE_SGTTY_H ${HAVE_SGTTY_H}
/* Define to 1 if you have the `sigaction' function. */
#cmakedefine HAVE_SIGACTION ${HAVE_SIGACTION}
/* Define to 1 if you have the `siginterrupt' function. */
#cmakedefine HAVE_SIGINTERRUPT ${HAVE_SIGINTERRUPT}
/* Define to 1 if you have the `signal' function. */
#cmakedefine HAVE_SIGNAL ${HAVE_SIGNAL}
/* If you have sigsetjmp */
#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP}
/* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET ${HAVE_SOCKET}
/* use SO_NONBLOCK for non-blocking sockets */
#cmakedefine HAVE_SO_NONBLOCK ${HAVE_SO_NONBLOCK}
/* Define this if you have the SPNEGO library fbopenssl */
#cmakedefine HAVE_SPNEGO ${HAVE_SPNEGO}
/* Define to 1 if you have the <ssl.h> header file. */
#cmakedefine HAVE_SSL_H ${HAVE_SSL_H}
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H}
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H}
/* Define to 1 if you have the `strcasecmp' function. */
#cmakedefine HAVE_STRCASECMP ${HAVE_STRCASECMP}
/* Define to 1 if you have the `strcmpi' function. */
#cmakedefine HAVE_STRCMPI ${HAVE_STRCMPI}
/* Define to 1 if you have the `strdup' function. */
#cmakedefine HAVE_STRDUP ${HAVE_STRDUP}
/* Define to 1 if you have the `strerror_r' function. */
#cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R}
/* Define to 1 if you have the `strftime' function. */
#cmakedefine HAVE_STRFTIME ${HAVE_STRFTIME}
/* Define to 1 if you have the `stricmp' function. */
#cmakedefine HAVE_STRICMP ${HAVE_STRICMP}
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H}
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H ${HAVE_STRING_H}
/* Define to 1 if you have the `strlcat' function. */
#cmakedefine HAVE_STRLCAT ${HAVE_STRLCAT}
/* Define to 1 if you have the `strlcpy' function. */
#cmakedefine HAVE_STRLCPY ${HAVE_STRLCPY}
/* Define to 1 if you have the `strstr' function. */
#cmakedefine HAVE_STRSTR ${HAVE_STRSTR}
/* Define to 1 if you have the `strtok_r' function. */
#cmakedefine HAVE_STRTOK_R ${HAVE_STRTOK_R}
/* Define to 1 if you have the `strtoll' function. */
#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL}
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H ${HAVE_SYS_IOCTL_H}
/* Define to 1 if you have the <sys/param.h> header file. */
#cmakedefine HAVE_SYS_PARAM_H ${HAVE_SYS_PARAM_H}
/* Define to 1 if you have the <sys/poll.h> header file. */
#cmakedefine HAVE_SYS_POLL_H ${HAVE_SYS_POLL_H}
/* Define to 1 if you have the <sys/select.h> header file. */
#cmakedefine HAVE_SYS_SELECT_H ${HAVE_SYS_SELECT_H}
/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}
/* Define to 1 if you have the <sys/sockio.h> header file. */
#cmakedefine HAVE_SYS_SOCKIO_H ${HAVE_SYS_SOCKIO_H}
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H}
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H ${HAVE_SYS_TIME_H}
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H}
/* Define to 1 if you have the <sys/utime.h> header file. */
#cmakedefine HAVE_SYS_UTIME_H ${HAVE_SYS_UTIME_H}
/* Define to 1 if you have the `tcgetattr' function. */
#cmakedefine HAVE_TCGETATTR ${HAVE_TCGETATTR}
/* Define to 1 if you have the `tcsetattr' function. */
#cmakedefine HAVE_TCSETATTR ${HAVE_TCSETATTR}
/* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
/* Define to 1 if you have the <termio.h> header file. */
#cmakedefine HAVE_TERMIO_H ${HAVE_TERMIO_H}
/* Define to 1 if you have the <time.h> header file. */
#cmakedefine HAVE_TIME_H ${HAVE_TIME_H}
/* Define to 1 if you have the `uname' function. */
#cmakedefine HAVE_UNAME ${HAVE_UNAME}
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H}
/* Define to 1 if you have the `utime' function. */
#cmakedefine HAVE_UTIME ${HAVE_UTIME}
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H}
/* Define to 1 if you have the <winsock.h> header file. */
#cmakedefine HAVE_WINSOCK_H ${HAVE_WINSOCK_H}
/* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV ${HAVE_WRITABLE_ARGV}
/* Define to 1 if you have the <x509.h> header file. */
#cmakedefine HAVE_X509_H ${HAVE_X509_H}
/* if you have the zlib.h header file */
#cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H}
/* need REENTRANT defined */
#cmakedefine NEED_REENTRANT ${NEED_REENTRANT}
/* cpu-machine-OS */
#define OS "${OPERATING_SYSTEM}"
@ -448,13 +445,34 @@
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
/* Define as the return type of signal handlers (`int' or `void'). */
#cmakedefine RETSIGTYPE ${RETSIGTYPE}
#cmakedefine RETSIGTYPE ${RETSIGTYPE}
/* Define to the type of arg 1 for `select'. */
#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1}
/* Define to the type of args 2, 3 and 4 for `select'. */
#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234}
/* Define to the type of arg 5 for `select'. */
#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5}
/* The size of a `curl_off_t', as computed by sizeof. */
#cmakedefine SIZEOF_CURL_OFF_T ${SIZEOF_CURL_OFF_T}
/* The size of a `size_t', as computed by sizeof. */
#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS ${STDC_HEADERS}
#cmakedefine STDC_HEADERS ${STDC_HEADERS}
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#cmakedefine TIME_WITH_SYS_TIME ${TIME_WITH_SYS_TIME}
#cmakedefine TIME_WITH_SYS_TIME ${TIME_WITH_SYS_TIME}
/* Define if you want to enable ares support */
#cmakedefine USE_ARES ${USE_ARES}
/* If you want to build curl with the built-in manual */
#cmakedefine USE_MANUAL ${USE_MANUAL}
/* Version number of package */
#cmakedefine VERSION "${VERSION}"
@ -467,25 +485,22 @@
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
/* Define for large files, on AIX-style hosts. */
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
/* Define to empty if `const' does not conform to ANSI C. */
#cmakedefine const ${const}
#cmakedefine const ${const}
/* type to use in place of in_addr_t if not defined */
#cmakedefine in_addr_t ${in_addr_t}
#cmakedefine in_addr_t ${in_addr_t}
/* Define to `unsigned' if <sys/types.h> does not define. */
#cmakedefine size_t ${size_t}
#cmakedefine size_t ${size_t}
/* type to use in place of socklen_t if not defined */
#cmakedefine socklen_t ${socklen_t}
#cmakedefine socklen_t ${socklen_t}
/* Define to `int' if <sys/types.h> does not define. */
#cmakedefine ssize_t ${ssize_t}
/* The number of bytes in a long double. */
#cmakedefine SIZEOF_LONG_DOUBLE ${SIZEOF_LONG_DOUBLE}
/* the signed version of size_t */
#cmakedefine ssize_t ${ssize_t}

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,18 @@
#ifndef __CONNECT_H
#define __CONNECT_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -23,18 +23,22 @@
* $Id$
***************************************************************************/
int Curl_nonblock(int socket, /* operate on this */
int Curl_nonblock(curl_socket_t sockfd, /* operate on this */
int nonblock /* TRUE or FALSE */);
CURLcode Curl_is_connected(struct connectdata *conn,
int sockfd,
int sockindex,
bool *connected);
CURLcode Curl_connecthost(struct connectdata *conn,
struct Curl_dns_entry *host, /* connect to this */
int port, /* connect to this port number */
int *sockconn, /* not set if error is returned */
Curl_ipconnect **addr, /* the one we used */
curl_socket_t *sockconn, /* not set if error */
Curl_addrinfo **addr, /* the one we used */
bool *connected /* truly connected? */
);
int Curl_ourerrno(void);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
#endif

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -25,13 +25,29 @@
#ifdef HAVE_LIBZ
#include <stdlib.h>
#include <string.h>
#include "urldata.h"
#include <curl/curl.h>
#include <curl/types.h>
#include "sendf.h"
#include "content_encoding.h"
#include "memory.h"
#define DSIZ 4096 /* buffer size for decompressed data */
#include "memdebug.h"
#define DSIZ 0x10000 /* buffer size for decompressed data */
#define GZIP_MAGIC_0 0x1f
#define GZIP_MAGIC_1 0x8b
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
static CURLcode
process_zlib_error(struct SessionHandle *data, z_stream *z)
@ -55,28 +71,30 @@ exit_zlib(z_stream *z, bool *zlib_init, CURLcode result)
}
CURLcode
Curl_unencode_deflate_write(struct SessionHandle *data,
Curl_unencode_deflate_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread)
{
int status; /* zlib status */
int result; /* Curl_client_write status */
CURLcode result = CURLE_OK; /* Curl_client_write status */
char decomp[DSIZ]; /* Put the decompressed data here. */
z_stream *z = &k->z; /* zlib state structure */
/* Initialize zlib? */
if (!k->zlib_init) {
z->zalloc = (alloc_func)Z_NULL;
z->zfree = (free_func)Z_NULL;
z->opaque = 0; /* of dubious use 08/27/02 jhrg */
z->opaque = 0;
z->next_in = NULL;
z->avail_in = 0;
if (inflateInit(z) != Z_OK)
return process_zlib_error(data, z);
k->zlib_init = 1;
}
/* Set the compressed input when this fucntion is called */
/* Set the compressed input when this function is called */
z->next_in = (Bytef *)k->str;
z->avail_in = nread;
z->avail_in = (uInt)nread;
/* because the buffer size is fixed, iteratively decompress
and transfer to the client via client_write. */
@ -87,24 +105,255 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
status = inflate(z, Z_SYNC_FLUSH);
if (status == Z_OK || status == Z_STREAM_END) {
result = Curl_client_write(data, CLIENTWRITE_BODY, decomp,
DSIZ - z->avail_out);
/* if !CURLE_OK, clean up, return */
if (result) {
return exit_zlib(z, &k->zlib_init, (CURLcode)result);
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, (CURLcode)result);
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 (CURLcode)result;
if (status == Z_OK && z->avail_in == 0 && z->avail_out > 0)
return result;
}
else { /* Error; exit loop, handle below */
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
}
/* Skip over the gzip header */
static enum {
GZIP_OK,
GZIP_BAD,
GZIP_UNDERFLOW
} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
{
int method, flags;
const ssize_t totallen = len;
/* The shortest header is 10 bytes */
if (len < 10)
return GZIP_UNDERFLOW;
if ((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
return GZIP_BAD;
method = data[2];
flags = data[3];
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
/* Can't handle this compression method or unknown flag */
return GZIP_BAD;
}
/* Skip over time, xflags, OS code and all previous bytes */
len -= 10;
data += 10;
if (flags & EXTRA_FIELD) {
ssize_t extra_len;
if (len < 2)
return GZIP_UNDERFLOW;
extra_len = (data[1] << 8) | data[0];
if (len < (extra_len+2))
return GZIP_UNDERFLOW;
len -= (extra_len + 2);
}
if (flags & ORIG_NAME) {
/* Skip over NUL-terminated file name */
while (len && *data) {
--len;
++data;
}
if (!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
++data;
}
if (flags & COMMENT) {
/* Skip over NUL-terminated comment */
while (len && *data) {
--len;
++data;
}
if (!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
++data;
}
if (flags & HEAD_CRC) {
if (len < 2)
return GZIP_UNDERFLOW;
len -= 2;
data += 2;
}
*headerlen = totallen - len;
return GZIP_OK;
}
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread)
{
int status; /* zlib status */
CURLcode result = CURLE_OK; /* Curl_client_write status */
char decomp[DSIZ]; /* Put the decompressed data here. */
z_stream *z = &k->z; /* zlib state structure */
/* Initialize zlib? */
if (!k->zlib_init) {
z->zalloc = (alloc_func)Z_NULL;
z->zfree = (free_func)Z_NULL;
z->opaque = 0;
z->next_in = NULL;
z->avail_in = 0;
if (inflateInit2(z, -MAX_WBITS) != Z_OK)
return process_zlib_error(data, z);
k->zlib_init = 1; /* Initial call state */
}
/* This next mess is to get around the potential case where there isn't
* enough data passed in to skip over the gzip header. If that happens, we
* malloc a block and copy what we have then wait for the next call. If
* there still isn't enough (this is definitely a worst-case scenario), we
* make the block bigger, copy the next part in and keep waiting.
*/
/* Skip over gzip header? */
if (k->zlib_init == 1) {
/* Initial call state */
ssize_t hlen;
switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
case GZIP_OK:
z->next_in = (Bytef *)k->str + hlen;
z->avail_in = (uInt)(nread - hlen);
k->zlib_init = 3; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We need more data so we can find the end of the gzip header. It's
* possible that the memory block we malloc here will never be freed if
* the transfer abruptly aborts after this point. Since it's unlikely
* that circumstances will be right for this code path to be followed in
* the first place, and it's even more unlikely for a transfer to fail
* immediately afterwards, it should seldom be a problem.
*/
z->avail_in = (uInt)nread;
z->next_in = malloc(z->avail_in);
if (z->next_in == NULL) {
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
memcpy(z->next_in, k->str, z->avail_in);
k->zlib_init = 2; /* Need more gzip header data state */
/* We don't have any data to inflate yet */
return CURLE_OK;
case GZIP_BAD:
default:
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
else if (k->zlib_init == 2) {
/* Need more gzip header data state */
ssize_t hlen;
unsigned char *oldblock = z->next_in;
z->avail_in += nread;
z->next_in = realloc(z->next_in, z->avail_in);
if (z->next_in == NULL) {
free(oldblock);
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
memcpy(z->next_in + z->avail_in - nread, k->str, nread);
switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
case GZIP_OK:
/* This is the zlib stream data */
free(z->next_in);
/* Don't point into the malloced block since we just freed it */
z->next_in = (Bytef *)k->str + hlen + nread - z->avail_in;
z->avail_in = (uInt)(z->avail_in - hlen);
k->zlib_init = 3; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We still don't have any data to inflate! */
return CURLE_OK;
case GZIP_BAD:
default:
free(z->next_in);
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
}
else {
/* Inflating stream state */
z->next_in = (Bytef *)k->str;
z->avail_in = (uInt)nread;
}
if (z->avail_in == 0) {
/* We don't have any data to inflate; wait until next time */
return CURLE_OK;
}
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via client_write. */
for (;;) {
/* (re)set buffer for decompressed output for every iteration */
z->next_out = (Bytef *)&decomp[0];
z->avail_out = DSIZ;
status = inflate(z, Z_SYNC_FLUSH);
if (status == Z_OK || status == Z_STREAM_END) {
if(DSIZ - z->avail_out) {
result = Curl_client_write(data, CLIENTWRITE_BODY, decomp,
DSIZ - z->avail_out);
/* if !CURLE_OK, clean up, return */
if (result)
return exit_zlib(z, &k->zlib_init, result);
}
/* Done?; clean up, return */
/* We should really check the gzip CRC here */
if (status == Z_STREAM_END) {
if (inflateEnd(z) == Z_OK)
return exit_zlib(z, &k->zlib_init, result);
else
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
}
/* Done with these bytes, exit */
if (status == Z_OK && z->avail_in == 0 && z->avail_out > 0)
return result;
}
else { /* Error; exit loop, handle below */
return exit_zlib(z, &k->zlib_init, process_zlib_error(data, z));
@ -112,11 +361,3 @@ Curl_unencode_deflate_write(struct SessionHandle *data,
}
}
#endif /* HAVE_LIBZ */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -20,15 +20,22 @@
*
* $Id$
***************************************************************************/
#include "setup.h"
/*
* Comma-separated list all supported Content-Encodings ('identity' is implied)
*/
#ifdef HAVE_LIBZ
#define ALL_CONTENT_ENCODINGS "deflate, gzip"
#else
#define ALL_CONTENT_ENCODINGS "identity"
#endif
CURLcode Curl_unencode_deflate_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread);
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
CURLcode
Curl_unencode_gzip_write(struct SessionHandle *data,
struct Curl_transfer_keeper *k,
ssize_t nread);

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -28,7 +28,7 @@ RECEIVING COOKIE INFORMATION
============================
struct CookieInfo *cookie_init(char *file);
Inits a cookie struct to store data in a local file. This is always
called before any cookies are set.
@ -58,9 +58,9 @@ struct Cookies *cookie_getlist(struct CookieInfo *cookie,
It shall only return cookies that haven't expired.
Example set of cookies:
Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
domain=.fidelity.com; path=/ftgw; secure
@ -77,6 +77,7 @@ Example set of cookies:
13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
****/
#include "setup.h"
#ifndef CURL_DISABLE_HTTP
@ -85,19 +86,23 @@ Example set of cookies:
#include <string.h>
#include <ctype.h>
#include "urldata.h"
#include "cookie.h"
#include "getdate.h"
#include "strequal.h"
#include "strtok.h"
#include "sendf.h"
#include "memory.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#ifdef CURLDEBUG
#include "memdebug.h"
#endif
static void
free_cookiemess(struct Cookie *co)
static void freecookie(struct Cookie *co)
{
if(co->expirestr)
free(co->expirestr);
if(co->domain)
free(co->domain);
if(co->path)
@ -110,6 +115,17 @@ free_cookiemess(struct Cookie *co)
free(co);
}
static bool tailmatch(const char *little, const char *bigone)
{
size_t littlelen = strlen(little);
size_t biglen = strlen(bigone);
if(littlelen > biglen)
return FALSE;
return (bool)strequal(little, bigone+biglen-littlelen);
}
/****************************************************************************
*
* Curl_cookie_add()
@ -119,13 +135,21 @@ free_cookiemess(struct Cookie *co)
***************************************************************************/
struct Cookie *
Curl_cookie_add(struct CookieInfo *c,
Curl_cookie_add(struct SessionHandle *data,
/* The 'data' pointer here may be NULL at times, and thus
must only be used very carefully for things that can deal
with data being NULL. Such as infof() and similar */
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
char *lineptr, /* first character of the line */
char *domain) /* default domain */
char *domain, /* default domain */
char *path) /* full path used when this cookie is set,
used to get default path for the cookie
unless set */
{
struct Cookie *clist;
char what[MAX_COOKIE_LINE];
char *what;
char name[MAX_NAME];
char *ptr;
char *semiptr;
@ -133,18 +157,23 @@ Curl_cookie_add(struct CookieInfo *c,
struct Cookie *lastc=NULL;
time_t now = time(NULL);
bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
/* First, alloc and init a new struct for it */
co = (struct Cookie *)malloc(sizeof(struct Cookie));
co = (struct Cookie *)calloc(sizeof(struct Cookie), 1);
if(!co)
return NULL; /* bail out if we're this low on memory */
/* clear the whole struct first */
memset(co, 0, sizeof(struct Cookie));
if(httpheader) {
/* This line was read off a HTTP-header */
char *sep;
what = malloc(MAX_COOKIE_LINE);
if(!what) {
free(co);
return NULL;
}
semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
while(*lineptr && isspace((int)*lineptr))
@ -183,13 +212,82 @@ Curl_cookie_add(struct CookieInfo *c,
if(strequal("path", name)) {
co->path=strdup(whatptr);
if(!co->path) {
badcookie = TRUE; /* out of memory bad */
break;
}
}
else if(strequal("domain", name)) {
co->domain=strdup(whatptr);
co->field1= (char)((whatptr[0]=='.')?2:1);
/* note that this name may or may not have a preceeding dot, but
we don't care about that, we treat the names the same anyway */
const char *domptr=whatptr;
int dotcount=1;
/* Count the dots, we need to make sure that there are enough
of them. */
if('.' == whatptr[0])
/* don't count the initial dot, assume it */
domptr++;
do {
domptr = strchr(domptr, '.');
if(domptr) {
domptr++;
dotcount++;
}
} while(domptr);
/* The original Netscape cookie spec defined that this domain name
MUST have three dots (or two if one of the seven holy TLDs),
but it seems that these kinds of cookies are in use "out there"
so we cannot be that strict. I've therefore lowered the check
to not allow less than two dots. */
if(dotcount < 2) {
/* Received and skipped a cookie with a domain using too few
dots. */
badcookie=TRUE; /* mark this as a bad cookie */
infof(data, "skipped cookie with illegal dotcount domain: %s\n",
whatptr);
}
else {
/* Now, we make sure that our host is within the given domain,
or the given domain is not valid and thus cannot be set. */
if('.' == whatptr[0])
whatptr++; /* ignore preceeding dot */
if(!domain || tailmatch(whatptr, domain)) {
const char *tailptr=whatptr;
if(tailptr[0] == '.')
tailptr++;
co->domain=strdup(tailptr); /* don't prefix w/dots
internally */
if(!co->domain) {
badcookie = TRUE;
break;
}
co->tailmatch=TRUE; /* we always do that if the domain name was
given */
}
else {
/* we did not get a tailmatch and then the attempted set domain
is not a domain to which the current host belongs. Mark as
bad. */
badcookie=TRUE;
infof(data, "skipped cookie with bad tailmatch domain: %s\n",
whatptr);
}
}
}
else if(strequal("version", name)) {
co->version=strdup(whatptr);
if(!co->version) {
badcookie = TRUE;
break;
}
}
else if(strequal("max-age", name)) {
/* Defined in RFC2109:
@ -202,16 +300,28 @@ Curl_cookie_add(struct CookieInfo *c,
*/
co->maxage = strdup(whatptr);
if(!co->maxage) {
badcookie = TRUE;
break;
}
co->expires =
atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + (long)now;
atoi((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0]) + now;
}
else if(strequal("expires", name)) {
co->expirestr=strdup(whatptr);
co->expires = (long)curl_getdate(what, &now);
if(!co->expirestr) {
badcookie = TRUE;
break;
}
co->expires = curl_getdate(what, &now);
}
else if(!co->name) {
co->name = strdup(name);
co->value = strdup(whatptr);
if(!co->name || !co->value) {
badcookie = TRUE;
break;
}
}
/*
else this is the second (or more) name we don't know
@ -248,23 +358,39 @@ Curl_cookie_add(struct CookieInfo *c,
semiptr=strchr(ptr, '\0');
} while(semiptr);
if(NULL == co->name) {
/* we didn't get a cookie name, this is an illegal line, bail out */
if(co->domain)
free(co->domain);
if(co->path)
free(co->path);
if(co->name)
free(co->name);
if(co->value)
free(co->value);
free(co);
if(!badcookie && !co->domain) {
if(domain) {
/* no domain was given in the header line, set the default */
co->domain=strdup(domain);
if(!co->domain)
badcookie = TRUE;
}
}
if(!badcookie && !co->path && path) {
/* no path was given in the header line, set the default */
char *endslash = strrchr(path, '/');
if(endslash) {
size_t pathlen = endslash-path+1; /* include the ending slash */
co->path=malloc(pathlen+1); /* one extra for the zero byte */
if(co->path) {
memcpy(co->path, path, pathlen);
co->path[pathlen]=0; /* zero terminate */
}
else
badcookie = TRUE;
}
}
free(what);
if(badcookie || !co->name) {
/* we didn't get a cookie name or a bad one,
this is an illegal line, bail out */
freecookie(co);
return NULL;
}
if(NULL == co->domain)
/* no domain given in the header line, set the default now */
co->domain=domain?strdup(domain):NULL;
}
else {
/* This line is NOT a HTTP header style line, we do offer support for
@ -286,7 +412,7 @@ Curl_cookie_add(struct CookieInfo *c,
if(ptr)
*ptr=0; /* clear it */
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* first tokenize it on the TAB */
firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
/* Here's a quick check to eliminate normal HTTP-headers from this */
if(!firstptr || strchr(firstptr, ':')) {
@ -296,10 +422,15 @@ Curl_cookie_add(struct CookieInfo *c,
/* Now loop through the fields and init the struct we already have
allocated */
for(ptr=firstptr, fields=0; ptr; ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
for(ptr=firstptr, fields=0; ptr && !badcookie;
ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
switch(fields) {
case 0:
if(ptr[0]=='.') /* skip preceeding dots */
ptr++;
co->domain = strdup(ptr);
if(!co->domain)
badcookie = TRUE;
break;
case 1:
/* This field got its explanation on the 23rd of May 2001 by
@ -311,10 +442,8 @@ Curl_cookie_add(struct CookieInfo *c,
As far as I can see, it is set to true when the cookie says
.domain.com and to false when the domain is complete www.domain.com
We don't currently take advantage of this knowledge.
*/
co->field1=(char)(strequal(ptr, "TRUE")+1); /* store information */
co->tailmatch=(bool)strequal(ptr, "TRUE"); /* store information */
break;
case 2:
/* It turns out, that sometimes the file format allows the path
@ -323,10 +452,14 @@ Curl_cookie_add(struct CookieInfo *c,
if (strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
/* only if the path doesn't look like a boolean option! */
co->path = strdup(ptr);
if(!co->path)
badcookie = TRUE;
break;
}
/* this doesn't look like a path, make one up! */
co->path = strdup("/");
if(!co->path)
badcookie = TRUE;
fields++; /* add a field and fall down to secure */
/* FALLTHROUGH */
case 3:
@ -337,17 +470,31 @@ Curl_cookie_add(struct CookieInfo *c,
break;
case 5:
co->name = strdup(ptr);
if(!co->name)
badcookie = TRUE;
break;
case 6:
co->value = strdup(ptr);
if(!co->value)
badcookie = TRUE;
break;
}
}
if(6 == fields) {
/* we got a cookie with blank contents, fix it */
co->value = strdup("");
if(!co->value)
badcookie = TRUE;
else
fields++;
}
if(7 != fields) {
/* we did not find the sufficient number of fields to recognize this
as a valid line, abort and go home */
free_cookiemess(co);
if(!badcookie && (7 != fields))
/* we did not find the sufficient number of fields */
badcookie = TRUE;
if(badcookie) {
freecookie(co);
return NULL;
}
@ -356,7 +503,7 @@ Curl_cookie_add(struct CookieInfo *c,
if(!c->running && /* read from a file */
c->newsession && /* clean session cookies */
!co->expires) { /* this is a session cookie since it doesn't expire! */
free_cookiemess(co);
freecookie(co);
return NULL;
}
@ -373,13 +520,8 @@ Curl_cookie_add(struct CookieInfo *c,
/* the names are identical */
if(clist->domain && co->domain) {
if(strequal(clist->domain, co->domain) ||
(clist->domain[0]=='.' &&
strequal(&(clist->domain[1]), co->domain)) ||
(co->domain[0]=='.' &&
strequal(clist->domain, &(co->domain[1]))) )
/* The domains are identical, or at least identical if you skip the
preceeding dot */
if(strequal(clist->domain, co->domain))
/* The domains are identical */
replace_old=TRUE;
}
else if(!clist->domain && !co->domain)
@ -399,7 +541,7 @@ Curl_cookie_add(struct CookieInfo *c,
replace_old = TRUE;
else
replace_old = FALSE;
}
if(replace_old && !co->livecookie && clist->livecookie) {
@ -409,16 +551,7 @@ Curl_cookie_add(struct CookieInfo *c,
live cookies stay alive */
/* Free the newcomer and get out of here! */
if(co->domain)
free(co->domain);
if(co->path)
free(co->path);
if(co->name)
free(co->name);
if(co->value)
free(co->value);
free(co);
freecookie(co);
return NULL;
}
@ -460,6 +593,12 @@ Curl_cookie_add(struct CookieInfo *c,
clist = clist->next;
}
if(c->running)
/* Only show this when NOT reading the cookies from a file */
infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, expire %d\n",
replace_old?"Replaced":"Added", co->name, co->value,
co->domain, co->path, co->expires);
if(!replace_old) {
/* then make the last item point on this new one */
if(lastc)
@ -469,7 +608,6 @@ Curl_cookie_add(struct CookieInfo *c,
}
c->numcookies++; /* one more cookie in the jar */
return co;
}
@ -483,21 +621,20 @@ Curl_cookie_add(struct CookieInfo *c,
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
*
****************************************************************************/
struct CookieInfo *Curl_cookie_init(char *file,
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
char *file,
struct CookieInfo *inc,
bool newsession)
{
char line[MAX_COOKIE_LINE];
struct CookieInfo *c;
FILE *fp;
bool fromfile=TRUE;
if(NULL == inc) {
/* we didn't get a struct, create one */
c = (struct CookieInfo *)malloc(sizeof(struct CookieInfo));
c = (struct CookieInfo *)calloc(1, sizeof(struct CookieInfo));
if(!c)
return NULL; /* failed to get memory */
memset(c, 0, sizeof(struct CookieInfo));
c->filename = strdup(file?file:"none"); /* copy the name just in case */
}
else {
@ -518,20 +655,25 @@ struct CookieInfo *Curl_cookie_init(char *file,
if(fp) {
char *lineptr;
bool headerline;
while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
headerline=TRUE;
}
else {
lineptr=line;
headerline=FALSE;
}
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(c, headerline, lineptr, NULL);
char *line = (char *)malloc(MAX_COOKIE_LINE);
if(line) {
while(fgets(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
headerline=TRUE;
}
else {
lineptr=line;
headerline=FALSE;
}
while(*lineptr && isspace((int)*lineptr))
lineptr++;
Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
}
free(line); /* free the line buffer */
}
if(fromfile)
fclose(fp);
@ -560,9 +702,6 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
struct Cookie *newco;
struct Cookie *co;
time_t now = time(NULL);
int hostlen=(int)strlen(host);
int domlen;
struct Cookie *mainco=NULL;
if(!c || !c->cookies)
@ -571,43 +710,52 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
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! */
/* 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 */
domlen=co->domain?(int)strlen(co->domain):0;
if(!co->domain ||
((domlen<=hostlen) &&
strequal(host+(hostlen-domlen), 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 ||
checkprefix(co->path, 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;
}
}
/* 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;
}
}
co = co->next;
}
return mainco; /* return the new list */
@ -652,24 +800,8 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
co = c->cookies;
while(co) {
if(co->name)
free(co->name);
if(co->value)
free(co->value);
if(co->domain)
free(co->domain);
if(co->path)
free(co->path);
if(co->expirestr)
free(co->expirestr);
if(co->version)
free(co->version);
if(co->maxage)
free(co->maxage);
next = co->next;
free(co);
freecookie(co);
co = next;
}
free(c); /* free the base struct as well */
@ -712,18 +844,22 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
co = c->cookies;
while(co) {
fprintf(out,
"%s\t" /* domain */
"%s\t" /* field1 */
"%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->field1==2?"TRUE":"FALSE",
co->tailmatch?"TRUE":"FALSE",
co->path?co->path:"/",
co->secure?"TRUE":"FALSE",
(unsigned int)co->expires,
@ -740,39 +876,4 @@ int Curl_cookie_output(struct CookieInfo *c, char *dumphere)
return 0;
}
#ifdef CURL_COOKIE_DEBUG
/*
* On my Solaris box, this command line builds this test program:
*
* gcc -g -o cooktest -DCURL_COOKIE_DEBUG -DHAVE_CONFIG_H -I.. -I../include cookie.c strequal.o getdate.o memdebug.o mprintf.o strtok.o -lnsl -lsocket
*
*/
int main(int argc, char **argv)
{
struct CookieInfo *c=NULL;
if(argc>1) {
c = Curl_cookie_init(argv[1], c);
Curl_cookie_add(c, TRUE, "PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/ftgw; secure");
Curl_cookie_add(c, TRUE, "foobar=yes; domain=.haxx.se; path=/looser;");
c = Curl_cookie_init(argv[1], c);
Curl_cookie_output(c);
Curl_cookie_cleanup(c);
return 0;
}
return 1;
}
#endif
#endif /* CURL_DISABLE_HTTP */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -1,18 +1,18 @@
#ifndef __COOKIE_H
#define __COOKIE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -40,13 +40,12 @@ struct Cookie {
char *domain; /* domain = <this> */
long expires; /* expires = <this> */
char *expirestr; /* the plain text version */
bool tailmatch; /* weather we do tail-matchning of the domain name */
char field1; /* read from a cookie file, 1 => FALSE, 2=> TRUE */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */
bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */
};
@ -61,22 +60,33 @@ struct CookieInfo {
bool newsession; /* new session, discard session cookies on load */
};
/* This is the maximum line length we accept for a cookie line */
#define MAX_COOKIE_LINE 2048
#define MAX_COOKIE_LINE_TXT "2047"
/* This is the maximum line length we accept for a cookie line. RFC 2109
section 6.3 says:
"at least 4096 bytes per cookie (as measured by the size of the characters
that comprise the cookie non-terminal in the syntax description of the
Set-Cookie header)"
*/
#define MAX_COOKIE_LINE 5000
#define MAX_COOKIE_LINE_TXT "4999"
/* This is the maximum length of a cookie name we deal with: */
#define MAX_NAME 256
#define MAX_NAME_TXT "255"
#define MAX_NAME 1024
#define MAX_NAME_TXT "1023"
struct SessionHandle;
/*
* Add a cookie to the internal list of cookies. The domain argument is only
* used if the header boolean is TRUE.
* Add a cookie to the internal list of cookies. The domain and path arguments
* are only used if the header boolean is TRUE.
*/
struct Cookie *Curl_cookie_add(struct CookieInfo *, bool header, char *line,
char *domain);
struct CookieInfo *Curl_cookie_init(char *, struct CookieInfo *, bool);
struct Cookie *Curl_cookie_add(struct SessionHandle *data,
struct CookieInfo *, bool header, char *line,
char *domain, char *path);
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
char *, struct CookieInfo *, bool);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, char *, char *, bool);
void Curl_cookie_freelist(struct Cookie *);
void Curl_cookie_cleanup(struct CookieInfo *);

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
#ifndef __CURL_CURLVER_H
#define __CURL_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.12.1"
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal. All three numbers are always represented using two digits. 1.2
would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
This 6-digit hexadecimal number does not show pre-release number, and it is
always a greater number in a more recent release. It makes comparisons with
greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x70C01
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 12
#define LIBCURL_VERSION_PATCH 1
#endif /* __CURL_CURLVER_H */

View File

@ -1,18 +1,18 @@
#ifndef __CURL_EASY_H
#define __CURL_EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -61,6 +61,19 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
*/
CURL* curl_easy_duphandle(CURL *curl);
/*
* NAME curl_easy_reset()
*
* DESCRIPTION
*
* Re-initializes a CURL handle to the default values. This puts back the
* handle to the same state as it was in when it was just created.
*
* It does keep: live connections, the Session ID cache, the DNS cache and the
* cookies.
*/
void curl_easy_reset(CURL *curl);
#ifdef __cplusplus
}
#endif

View File

@ -1,54 +1,25 @@
/*************************************************************************
/***************************************************************************
* _ _ ____ _
* 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$
*
* 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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
* CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
*
*************************************************************************
*
* Preliminary documentation
*
* printf conversions:
*
* conversion ::= '%%' | '%' [position] ( number | float | string )
* position ::= digits '$'
* number ::= [number-flags] ( 'd' | 'i' | 'o' | 'x' | 'X' | 'u')
* number-flags ::= 'h' | 'l' | 'L' ...
* float ::= [float-flags] ( 'f' | 'e' | 'E' | 'g' | 'G' )
* string ::= [string-flags] 's'
* string-flags ::= padding | '#'
* digits ::= (digit)+
* digit ::= 0-9
*
* c
* p
* n
*
* qualifiers
*
* - : left adjustment
* + : show sign
* SPACE : padding
* # : alterative
* . : precision
* * : width
* 0 : padding / size
* 1-9 : size
* h : short
* l : long
* ll : longlong
* L : long double
* Z : long / longlong
* q : longlong
*
************************************************************************/
***************************************************************************/
#ifndef H_MPRINTF
#define H_MPRINTF

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -44,19 +44,35 @@
o Enable the application to select() on its own file descriptors and curl's
file descriptors simultaneous easily.
Example sources using this interface is here: ../multi/
*/
#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 <winsock.h>
#include <winsock2.h>
#else
/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
libc5-based Linux systems. Only include it on system that are known to
require it! */
#if defined(_AIX) || defined(NETWARE)
#include <sys/select.h>
#endif
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#endif
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void CURLM;
typedef enum {
@ -71,7 +87,7 @@ typedef enum {
typedef enum {
CURLMSG_NONE, /* first, not used */
CURLMSG_DONE, /* This easy handle has completed. 'whatever' points to
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
the CURLcode of the transfer */
CURLMSG_LAST /* last, not used */
} CURLMSG;
@ -187,4 +203,19 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle);
CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue);
/*
* NAME curl_multi_strerror()
*
* DESCRIPTION
*
* The curl_multi_strerror function may be used to turn a CURLMcode value
* into the equivalent human readable error string. This is useful
* for printing meaningful error messages.
*/
const char *curl_multi_strerror(CURLMcode);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -23,9 +23,7 @@
* $Id$
***************************************************************************/
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
size_t fread (void *, size_t, size_t, FILE *);
size_t fwrite (const void *, size_t, size_t, FILE *);

View File

@ -1,28 +1 @@
#ifndef __CURL_TYPES_H
#define __CURL_TYPES_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
typedef void CURL;
typedef void CURLconnect;
#endif /* __CURL_TYPES_H */
/* not used */

95
Source/CTest/Curl/curlx.h Normal file
View File

@ -0,0 +1,95 @@
#ifndef __CURLX_H
#define __CURLX_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
/*
* Defines protos and includes all header files that provide the curlx_*
* functions. The curlx_* functions are not part of the libcurl API, but are
* stand-alone functions whose sources can be built and linked by apps if need
* be.
*/
#include <curl/mprintf.h>
/* this is still a public header file that provides the curl_mprintf()
functions while they still are offered publicly. They will be made library-
private one day */
#include "strequal.h"
/* "strequal.h" provides the strequal protos */
#include "strtoofft.h"
/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a
curl_off_t number from a given string.
*/
#include "timeval.h"
/*
"timeval.h" sets up a 'struct timeval' even for platforms that otherwise
don't have one and has protos for these functions:
curlx_tvnow()
curlx_tvdiff()
curlx_tvdiff_secs()
*/
/* Now setup curlx_ * names for the functions that are to become curlx_ and
be removed from a future libcurl official API:
curlx_getenv
curlx_mprintf (and its variations)
curlx_strequal
curlx_strnequal
*/
#define curlx_getenv curl_getenv
#define curlx_strequal curl_strequal
#define curlx_strnequal curl_strnequal
#define curlx_mvsnprintf curl_mvsnprintf
#define curlx_msnprintf curl_msnprintf
#define curlx_maprintf curl_maprintf
#define curlx_mvaprintf curl_mvaprintf
#define curlx_msprintf curl_msprintf
#define curlx_mprintf curl_mprintf
#define curlx_mfprintf curl_mfprintf
#define curlx_mvsprintf curl_mvsprintf
#define curlx_mvprintf curl_mvprintf
#define curlx_mvfprintf curl_mvfprintf
#ifdef ENABLE_CURLX_PRINTF
/* If this define is set, we define all "standard" printf() functions to use
the curlx_* version instead. It makes the source code transparant and
easier to understand/patch. */
# define printf curlx_mprintf
# define fprintf curlx_mfprintf
# define sprintf curlx_msprintf
# define snprintf curlx_msnprintf
# define vprintf curlx_mvprintf
# define vfprintf curlx_mvfprintf
# define vsprintf curlx_mvsprintf
# define vsnprintf curlx_mvsnprintf
# define aprintf curlx_maprintf
# define vaprintf curlx_mvaprintf
#endif /* ENABLE_CURLX_PRINTF */
#endif /* __CURLX_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -35,7 +35,6 @@
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
#include <io.h>
#else
@ -44,7 +43,6 @@
#endif
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -76,13 +74,13 @@
#include "progress.h"
#include "strequal.h"
#include "dict.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
CURLcode Curl_dict(struct connectdata *conn)
{
int nth;
char *word;
char *ppath;
char *database = NULL;
@ -91,9 +89,10 @@ CURLcode Curl_dict(struct connectdata *conn)
by RFC 2229 */
CURLcode result=CURLE_OK;
struct SessionHandle *data=conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = conn->path;
long *bytecount = &conn->bytecount;
curl_off_t *bytecount = &conn->bytecount;
if(conn->bits.user_passwd) {
/* AUTH is missing */
@ -129,14 +128,8 @@ CURLcode Curl_dict(struct connectdata *conn)
if ((strategy == NULL) || (*strategy == (char)0)) {
strategy = (char *)".";
}
if ((nthdef == NULL) || (*nthdef == (char)0)) {
nth = 0;
}
else {
nth = atoi(nthdef);
}
result = Curl_sendf(conn->firstsocket, conn,
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH "
"%s " /* database */
@ -151,7 +144,7 @@ CURLcode Curl_dict(struct connectdata *conn)
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
return result;
@ -179,14 +172,8 @@ CURLcode Curl_dict(struct connectdata *conn)
if ((database == NULL) || (*database == (char)0)) {
database = (char *)"!";
}
if ((nthdef == NULL) || (*nthdef == (char)0)) {
nth = 0;
}
else {
nth = atoi(nthdef);
}
result = Curl_sendf(conn->firstsocket, conn,
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE "
"%s " /* database */
@ -197,7 +184,7 @@ CURLcode Curl_dict(struct connectdata *conn)
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
@ -215,27 +202,19 @@ CURLcode Curl_dict(struct connectdata *conn)
if (ppath[i] == ':')
ppath[i] = ' ';
}
result = Curl_sendf(conn->firstsocket, conn,
result = Curl_sendf(sockfd, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"%s\n"
"QUIT\n", ppath);
if(result)
failf(data, "Failed sending DICT request");
else
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL);
if(result)
return result;
}
}
(void)nth;
return CURLE_OK;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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

View File

@ -1,96 +0,0 @@
#ifdef WIN32
/* dllinit.c -- Portable DLL initialization.
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Contributed by Mumit Khan (khan@xraylith.wisc.edu).
I've used DllMain as the DLL "main" since that's the most common
usage. MSVC and Mingw32 both default to DllMain as the standard
callback from the linker entry point. Cygwin, as of b20.1, also
uses DllMain as the default callback from the entry point.
The real entry point is typically always defined by the runtime
library, and usually never overridden by (casual) user. What you can
override however is the callback routine that the entry point calls,
and this file provides such a callback function, DllMain.
Mingw32: The default entry point for mingw32 is DllMainCRTStartup
which is defined in libmingw32.a This in turn calls DllMain which is
defined here. If not defined, there is a stub in libmingw32.a which
does nothing.
Cygwin: The default entry point for Cygwin b20.1 or newer is
__cygwin_dll_entry which is defined in libcygwin.a. This in turn
calls the routine DllMain. If not defined, there is a stub in
libcygwin.a which does nothing.
MSVC: MSVC runtime calls DllMain, just like Mingw32.
Summary: If you need to do anything special in DllMain, just add it
here. Otherwise, the default setup should be just fine for 99%+ of
the time. I strongly suggest that you *not* change the entry point,
but rather change DllMain as appropriate.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <stdio.h>
BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason,
LPVOID reserved /* Not used. */ );
/*
*----------------------------------------------------------------------
*
* DllMain --
*
* This routine is called by the Mingw32, Cygwin32 or VC++ C run
* time library init code, or the Borland DllEntryPoint routine. It
* is responsible for initializing various dynamically loaded
* libraries.
*
* Results:
* TRUE on sucess, FALSE on failure.
*
* Side effects:
*
*----------------------------------------------------------------------
*/
BOOL APIENTRY
DllMain (
HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
#else
#ifdef VMS
int VOID_VAR_DLLINIT;
#endif
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -37,7 +37,6 @@
#include "strequal.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
#include <io.h>
#else
@ -46,7 +45,6 @@
#endif
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -68,7 +66,7 @@
#include <sys/select.h>
#endif
#endif
#endif /* WIN32 ... */
#include "urldata.h"
#include <curl/curl.h>
@ -77,70 +75,120 @@
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
#include "share.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* Silly win32 socket initialization functions */
/* The last #include file should be: */
#include "memdebug.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
of win32_init() */
static void win32_cleanup(void)
{
WSACleanup();
}
/* win32_init() performs win32 socket initialization to properly setup the
stack to allow networking */
static CURLcode win32_init(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 0);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return CURLE_FAILED_INIT;
/* Confirm that the Windows Sockets DLL supports 2.0.*/
/* Note that if the DLL supports versions greater */
/* than 2.0 in addition to 2.0, it will still return */
/* 2.0 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 ) {
/* Tell the user that we couldn't find a useable */
WORD wVersionRequested;
WSADATA wsaData;
int err;
/* winsock.dll. */
WSACleanup();
return CURLE_FAILED_INIT;
#ifdef ENABLE_IPV6
wVersionRequested = MAKEWORD(2, 0);
#else
wVersionRequested = MAKEWORD(1, 1);
#endif
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return CURLE_FAILED_INIT;
/* Confirm that the Windows Sockets DLL supports what we need.*/
/* Note that if the DLL supports versions greater */
/* than wVersionRequested, it will still return */
/* wVersionRequested in wVersion. wHighVersion contains the */
/* highest supported version. */
if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return CURLE_FAILED_INIT;
}
/* The Windows Sockets DLL is acceptable. Proceed. */
return CURLE_OK;
}
/* The Windows Sockets DLL is acceptable. Proceed. */
#else
/* These functions exist merely to prevent compiler warnings */
static CURLcode win32_init(void) { return CURLE_OK; }
static void win32_cleanup(void) { }
#endif
#ifdef USE_LIBIDN
/*
* Initialise use of IDNA library.
* It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
* idna_to_ascii_lz().
*/
static void idna_init (void)
{
#ifdef WIN32
char buf[60];
UINT cp = GetACP();
if (!getenv("CHARSET") && cp > 0) {
snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
putenv(buf);
}
#else
/* to do? */
#endif
}
#endif /* USE_LIBIDN */
/* true globals -- for curl_global_init() and curl_global_cleanup() */
static unsigned int initialized = 0;
static long init_flags = 0;
/*
* If a memory-using function (like curl_getenv) is used before
* curl_global_init() is called, we need to have these pointers set already.
*/
curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
/**
* Globally initializes cURL given a bitwise set of
* the different features to initialize.
* curl_global_init() globally initializes cURL given a bitwise set of the
* different features of what to initialize.
*/
CURLcode curl_global_init(long flags)
{
if (initialized)
return CURLE_OK;
/* Setup the default memory functions here (again) */
Curl_cmalloc = (curl_malloc_callback)malloc;
Curl_cfree = (curl_free_callback)free;
Curl_crealloc = (curl_realloc_callback)realloc;
Curl_cstrdup = (curl_strdup_callback)strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
if (flags & CURL_GLOBAL_SSL)
Curl_SSL_init();
@ -148,15 +196,55 @@ CURLcode curl_global_init(long flags)
if (win32_init() != CURLE_OK)
return CURLE_FAILED_INIT;
#ifdef _AMIGASF
if(!amiga_init())
return CURLE_FAILED_INIT;
#endif
#ifdef USE_LIBIDN
idna_init();
#endif
initialized = 1;
init_flags = flags;
return CURLE_OK;
}
/*
* curl_global_init_mem() globally initializes cURL and also registers the
* user provided callback routines.
*/
CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
curl_free_callback f, curl_realloc_callback r,
curl_strdup_callback s, curl_calloc_callback c)
{
CURLcode code = CURLE_OK;
/* Invalid input, return immediately */
if (!m || !f || !r || !s || !c)
return CURLE_FAILED_INIT;
/* Already initialized, don't do it again */
if ( initialized )
return CURLE_OK;
/* Call the actual init function first */
code = curl_global_init(flags);
if (code == CURLE_OK) {
Curl_cmalloc = m;
Curl_cfree = f;
Curl_cstrdup = s;
Curl_crealloc = r;
Curl_ccalloc = c;
}
return code;
}
/**
* Globally cleanup cURL, uses the value of "init_flags" to determine
* what needs to be cleaned up and what doesn't
* curl_global_cleanup() globally cleanups cURL, uses the value of
* "init_flags" to determine what needs to be cleaned up and what doesn't.
*/
void curl_global_cleanup(void)
{
@ -171,18 +259,30 @@ void curl_global_cleanup(void)
if (init_flags & CURL_GLOBAL_WIN32)
win32_cleanup();
#ifdef _AMIGASF
amiga_cleanup();
#endif
initialized = 0;
init_flags = 0;
}
/*
* curl_easy_init() is the external interface to alloc, setup and init an
* easy handle that is returned. If anything goes wrong, NULL is returned.
*/
CURL *curl_easy_init(void)
{
CURLcode res;
struct SessionHandle *data;
/* Make sure we inited the global SSL stuff */
if (!initialized)
curl_global_init(CURL_GLOBAL_DEFAULT);
if (!initialized) {
res = curl_global_init(CURL_GLOBAL_DEFAULT);
if(res)
/* something in the global init failed, return nothing */
return NULL;
}
/* We use curl_open() with undefined URL so far */
res = Curl_open(&data);
@ -192,6 +292,10 @@ CURL *curl_easy_init(void)
return data;
}
/*
* curl_easy_setopt() is the external interface for setting options on an
* easy handle.
*/
typedef int (*func_T)(void);
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
{
@ -199,7 +303,12 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
func_T param_func = (func_T)0;
long param_long = 0;
void *param_obj = NULL;
curl_off_t param_offset = 0;
struct SessionHandle *data = curl;
CURLcode ret=CURLE_FAILED_INIT;
if(!curl)
return CURLE_BAD_FUNCTION_ARGUMENT;
va_start(arg, tag);
@ -213,49 +322,86 @@ CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
if(tag < CURLOPTTYPE_OBJECTPOINT) {
/* This is a LONG type */
param_long = va_arg(arg, long);
Curl_setopt(data, tag, param_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 *);
Curl_setopt(data, tag, param_obj);
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 {
param_func = va_arg(arg, func_T );
Curl_setopt(data, tag, param_func);
/* This is a curl_off_t type */
param_offset = va_arg(arg, curl_off_t);
ret = Curl_setopt(data, tag, param_offset);
}
va_end(arg);
return CURLE_OK;
return ret;
}
/*
* curl_easy_perform() is the external interface that performs a transfer
* previously setup.
*/
CURLcode curl_easy_perform(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
if (Curl_global_host_cache_use(data) && data->hostcache != Curl_global_host_cache_get()) {
if (data->hostcache) {
Curl_hash_destroy(data->hostcache);
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
if ( ! (data->share && data->share->hostcache) ) {
if (Curl_global_host_cache_use(data) &&
data->hostcache != Curl_global_host_cache_get()) {
if (data->hostcache)
Curl_hash_destroy(data->hostcache);
data->hostcache = Curl_global_host_cache_get();
}
data->hostcache = Curl_global_host_cache_get();
if (!data->hostcache) {
data->hostcache = Curl_mk_dnscache();
if(!data->hostcache)
/* While we possibly could survive and do good without a host cache,
the fact that creating it failed indicates that things are truly
screwed up and we should bail out! */
return CURLE_OUT_OF_MEMORY;
}
}
if (!data->hostcache) {
data->hostcache = Curl_hash_alloc(7, Curl_freednsinfo);
}
return Curl_perform(data);
}
/*
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
* easy handle.
*/
void curl_easy_cleanup(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
if (!Curl_global_host_cache_use(data)) {
Curl_hash_destroy(data->hostcache);
if(!data)
return;
if ( ! (data->share && data->share->hostcache) ) {
if ( !Curl_global_host_cache_use(data)) {
Curl_hash_destroy(data->hostcache);
}
}
Curl_close(data);
}
/*
* curl_easy_getinfo() is an external interface that allows an app to retrieve
* information from a performed transfer and similar.
*/
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
{
va_list arg;
@ -268,76 +414,170 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
return Curl_getinfo(data, info, paramp);
}
/*
* curl_easy_duphandle() is an external interface to allow duplication of a
* given input easy handle. The returned handle will be a new working handle
* with all options set exactly as the input source handle.
*/
CURL *curl_easy_duphandle(CURL *incurl)
{
bool fail = TRUE;
struct SessionHandle *data=(struct SessionHandle *)incurl;
struct SessionHandle *outcurl = (struct SessionHandle *)
malloc(sizeof(struct SessionHandle));
calloc(sizeof(struct SessionHandle), 1);
if(NULL == outcurl)
return NULL; /* failure */
/* start with clearing the entire new struct */
memset(outcurl, 0, sizeof(struct SessionHandle));
do {
/*
* We setup a few buffers we need. We should probably make them
* get setup on-demand in the code, as that would probably decrease
* the likeliness of us forgetting to init a buffer here in the future.
*/
outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
if(!outcurl->state.headerbuff) {
free(outcurl); /* free the memory again */
return NULL;
}
outcurl->state.headersize=HEADERSIZE;
/*
* We setup a few buffers we need. We should probably make them
* get setup on-demand in the code, as that would probably decrease
* the likeliness of us forgetting to init a buffer here in the future.
*/
outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
if(!outcurl->state.headerbuff) {
break;
}
outcurl->state.headersize=HEADERSIZE;
/* copy all userdefined values */
outcurl->set = data->set;
outcurl->state.numconnects = data->state.numconnects;
outcurl->state.connects = (struct connectdata **)
/* 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) {
free(outcurl->state.headerbuff);
free(outcurl);
return NULL;
}
memset(outcurl->state.connects, 0,
sizeof(struct connectdata *)*outcurl->state.numconnects);
if(!outcurl->state.connects) {
break;
}
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
memset(outcurl->state.connects, 0,
sizeof(struct connectdata *)*outcurl->state.numconnects);
if(data->cookies)
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
outcurl->cookies = Curl_cookie_init(data->cookies->filename,
outcurl->cookies,
data->set.cookiesession);
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
/* duplicate all values in 'change' */
if(data->change.url) {
outcurl->change.url = strdup(data->change.url);
outcurl->change.url_alloc = TRUE;
}
if(data->change.proxy) {
outcurl->change.proxy = strdup(data->change.proxy);
outcurl->change.proxy_alloc = TRUE;
}
if(data->change.referer) {
outcurl->change.referer = strdup(data->change.referer);
outcurl->change.referer_alloc = TRUE;
#ifndef CURL_DISABLE_HTTP
if(data->cookies) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
outcurl->cookies = Curl_cookie_init(data,
data->cookies->filename,
outcurl->cookies,
data->set.cookiesession);
if(!outcurl->cookies) {
break;
}
}
#endif /* CURL_DISABLE_HTTP */
/* duplicate all values in 'change' */
if(data->change.url) {
outcurl->change.url = strdup(data->change.url);
if(!outcurl->change.url)
break;
outcurl->change.url_alloc = TRUE;
}
if(data->change.proxy) {
outcurl->change.proxy = strdup(data->change.proxy);
if(!outcurl->change.proxy)
break;
outcurl->change.proxy_alloc = TRUE;
}
if(data->change.referer) {
outcurl->change.referer = strdup(data->change.referer);
if(!outcurl->change.referer)
break;
outcurl->change.referer_alloc = TRUE;
}
#ifdef USE_ARES
/* If we use ares, we setup a new ares channel for the new handle */
if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
break;
#endif
fail = FALSE; /* we reach this point and thus we are OK */
} while(0);
if(fail) {
if(outcurl) {
if(outcurl->state.connects)
free(outcurl->state.connects);
if(outcurl->state.headerbuff)
free(outcurl->state.headerbuff);
if(outcurl->change.proxy)
free(outcurl->change.proxy);
if(outcurl->change.url)
free(outcurl->change.url);
if(outcurl->change.referer)
free(outcurl->change.referer);
free(outcurl); /* free the memory again */
outcurl = NULL;
}
}
return outcurl;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
* curl_easy_reset() is an external interface that allows an app to re-
* initialize a session handle to the default values.
*/
void curl_easy_reset(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
/* zero out UserDefined data: */
memset(&data->set, 0, sizeof(struct UserDefined));
/* zero out Progress data: */
memset(&data->progress, 0, sizeof(struct Progress));
/* The remainder of these calls have been taken from Curl_open() */
data->set.out = stdout; /* default output to stdout */
data->set.in = stdin; /* default input from stdin */
data->set.err = stderr; /* default stderr to stderr */
/* use fwrite as default function to store output */
data->set.fwrite = (curl_write_callback)fwrite;
/* use fread as default function to read input */
data->set.fread = (curl_read_callback)fread;
data->set.infilesize = -1; /* we don't know any size */
data->state.current_speed = -1; /* init to negative == impossible */
data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
data->set.ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
/* make libcurl quiet by default: */
data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
/* Set the default size of the SSL session ID cache */
data->set.ssl.numsessions = 5;
data->set.proxyport = 1080;
data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic */
data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
/*
* libcurl 7.10 introduced SSL verification *by default*! This needs to be
* switched off unless wanted.
*/
data->set.ssl.verifypeer = TRUE;
data->set.ssl.verifyhost = 2;
#ifdef CURL_CA_BUNDLE
/* This is our prefered CA cert bundle since install time */
data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
#endif
}

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -31,20 +31,27 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
char *curl_escape(const char *string, int length)
char *curl_escape(const char *string, int inlength)
{
int alloc = (length?length:(int)strlen(string))+1;
char *ns = malloc(alloc);
size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
char *ns;
char *testing_ptr = NULL;
unsigned char in;
int newlen = alloc;
int index=0;
size_t newlen = alloc;
int strindex=0;
size_t length;
ns = malloc(alloc);
if(!ns)
return NULL;
length = alloc-1;
while(length--) {
@ -65,59 +72,64 @@ char *curl_escape(const char *string, int length)
ns = testing_ptr;
}
}
sprintf(&ns[index], "%%%02X", in);
snprintf(&ns[strindex], 4, "%%%02X", in);
index+=3;
strindex+=3;
}
else {
/* just copy this */
ns[index++]=in;
ns[strindex++]=in;
}
string++;
}
ns[index]=0; /* terminate it */
ns[strindex]=0; /* terminate it */
return ns;
}
#define ishex(in) ((in >= 'a' && in <= 'f') || \
(in >= 'A' && in <= 'F') || \
(in >= '0' && in <= '9'))
char *curl_unescape(const char *string, int length)
{
int alloc = (length?length:(int)strlen(string))+1;
char *ns = malloc(alloc);
unsigned char in;
int index=0;
unsigned int hex;
if( !ns ) {
int strindex=0;
long hex;
if( !ns )
return NULL;
}
while(--alloc > 0) {
in = *string;
if('%' == in) {
/* encoded part */
if(sscanf(string+1, "%02X", &hex)) {
in = (unsigned char)hex;
string+=2;
alloc-=2;
}
if(('%' == in) && ishex(string[1]) && ishex(string[2])) {
/* this is two hexadecimal digits following a '%' */
char hexstr[3];
char *ptr;
hexstr[0] = string[1];
hexstr[1] = string[2];
hexstr[2] = 0;
hex = strtol(hexstr, &ptr, 16);
in = (unsigned char)hex; /* this long is never bigger than 255 anyway */
string+=2;
alloc-=2;
}
ns[index++] = in;
ns[strindex++] = in;
string++;
}
ns[index]=0; /* terminate it */
ns[strindex]=0; /* terminate it */
return ns;
}
/* For operating systems/environments that use different malloc/free
ssystems for the app and for this library, we provide a free that uses
the library's memory system */
void curl_free(void *p)
{
free(p);
if(p)
free(p);
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -36,7 +36,6 @@
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>
@ -48,7 +47,6 @@
#include <netinet/in.h>
#endif
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -75,7 +73,6 @@
#include <fcntl.h>
#endif
#endif
#include "urldata.h"
@ -83,46 +80,85 @@
#include "progress.h"
#include "sendf.h"
#include "escape.h"
#include "file.h"
#include "speedcheck.h"
#include "getinfo.h"
#include "transfer.h"
#include "url.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* Emulate a connect-then-transfer protocol. We connect to the file here */
/*
* Curl_file_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. We emulate a
* connect-then-transfer protocol and "connect" to the file here
*/
CURLcode Curl_file_connect(struct connectdata *conn)
{
char *actual_path = curl_unescape(conn->path, 0);
struct FILE *file;
char *real_path = curl_unescape(conn->path, 0);
struct FILEPROTO *file;
int fd;
#if defined(WIN32) || defined(__EMX__)
int i;
char *actual_path;
#endif
file = (struct FILE *)malloc(sizeof(struct FILE));
if(!file)
if(!real_path)
return CURLE_OUT_OF_MEMORY;
memset(file, 0, sizeof(struct FILE));
file = (struct FILEPROTO *)calloc(sizeof(struct FILEPROTO), 1);
if(!file) {
free(real_path);
return CURLE_OUT_OF_MEMORY;
}
conn->proto.file = file;
#if defined(WIN32) || defined(__EMX__)
/* If the first character is a slash, and there's
something that looks like a drive at the beginning of
the path, skip the slash. If we remove the initial
slash in all cases, paths without drive letters end up
relative to the current directory which isn't how
browsers work.
Some browsers accept | instead of : as the drive letter
separator, so we do too.
On other platforms, we need the slash to indicate an
absolute pathname. On Windows, absolute paths start
with a drive letter.
*/
actual_path = real_path;
if ((actual_path[0] == '/') &&
actual_path[1] &&
(actual_path[2] == ':' || actual_path[2] == '|'))
{
actual_path[2] = ':';
actual_path++;
}
/* change path separators from '/' to '\\' for Windows and OS/2 */
for (i=0; actual_path[i] != '\0'; ++i)
if (actual_path[i] == '/')
actual_path[i] = '\\';
fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */
file->path = actual_path;
#else
fd = open(actual_path, O_RDONLY);
fd = open(real_path, O_RDONLY);
file->path = real_path;
#endif
free(actual_path);
file->freepath = real_path; /* free this when done */
if(fd == -1) {
if(!conn->data->set.upload && (fd == -1)) {
failf(conn->data, "Couldn't open file %s", conn->path);
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE);
return CURLE_FILE_COULDNT_READ_FILE;
}
file->fd = fd;
@ -130,35 +166,174 @@ CURLcode Curl_file_connect(struct connectdata *conn)
return CURLE_OK;
}
/* This is the do-phase, separated from the connect-phase above */
#if defined(WIN32) && (SIZEOF_CURL_OFF_T > 4)
#define lseek(x,y,z) _lseeki64(x, y, z)
#endif
CURLcode Curl_file_done(struct connectdata *conn,
CURLcode status)
{
struct FILEPROTO *file = conn->proto.file;
(void)status; /* not used */
Curl_safefree(file->freepath);
return CURLE_OK;
}
#if defined(WIN32) || defined(__EMX__)
#define DIRSEP '\\'
#else
#define DIRSEP '/'
#endif
static CURLcode file_upload(struct connectdata *conn)
{
struct FILEPROTO *file = conn->proto.file;
char *dir = strchr(file->path, DIRSEP);
FILE *fp;
CURLcode res=CURLE_OK;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
size_t nread;
size_t nwrite;
curl_off_t bytecount = 0;
struct timeval now = Curl_tvnow();
/*
* Since FILE: doesn't do the full init, we need to provide some extra
* assignments here.
*/
conn->fread = data->set.fread;
conn->fread_in = data->set.in;
conn->upload_fromhere = buf;
if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
if(!dir[1])
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
fp = fopen(file->path, "wb");
if(!fp) {
failf(data, "Can't open %s for writing", file->path);
return CURLE_WRITE_ERROR;
}
if(-1 != data->set.infilesize)
/* known size of data to "upload" */
Curl_pgrsSetUploadSize(data, data->set.infilesize);
while (res == CURLE_OK) {
int readcount;
res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
if(res)
return res;
nread = (size_t)readcount;
if (nread <= 0)
break;
/* write the data to the target */
nwrite = fwrite(buf, 1, nread, fp);
if(nwrite != nread) {
res = CURLE_SEND_ERROR;
break;
}
bytecount += nread;
Curl_pgrsSetUploadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
else
res = Curl_speedcheck(data, now);
}
if(!res && Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
fclose(fp);
return res;
}
/*
* Curl_file() is the protocol-specific function for the do-phase, separated
* from the connect-phase above. Other protocols merely setup the transfer in
* the do-phase, to have it done in the main transfer loop but since some
* platforms we support don't allow select()ing etc on file handles (as
* opposed to sockets) we instead perform the whole do-operation in this
* function.
*/
CURLcode Curl_file(struct connectdata *conn)
{
/* This implementation ignores the host name in conformance with
/* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system)
are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
CURLcode res = CURLE_OK;
struct stat statbuf;
double expected_size=-1;
curl_off_t expected_size=0;
bool fstated=FALSE;
ssize_t nread;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
int bytecount = 0;
struct timeval start = Curl_tvnow();
struct timeval now = start;
curl_off_t bytecount = 0;
int fd;
struct timeval now = Curl_tvnow();
(void)now;
Curl_readwrite_init(conn);
Curl_initinfo(data);
Curl_pgrsStartNow(data);
if(data->set.upload)
return file_upload(conn);
/* get the fd from the connection phase */
fd = conn->proto.file->fd;
/*VMS?? -- This only works reliable for STREAMLF files */
/* VMS: This only works reliable for STREAMLF files */
if( -1 != fstat(fd, &statbuf)) {
/* we could stat it, then read out the size */
expected_size = (double)statbuf.st_size;
expected_size = statbuf.st_size;
fstated = TRUE;
}
/* If we have selected NOBODY and HEADER, it means that we only want file
information. Which for FILE can't be much more than the file size and
date. */
if(conn->bits.no_body && data->set.include_header && fstated) {
CURLcode result;
snprintf(buf, sizeof(data->state.buffer),
"Content-Length: %" FORMAT_OFF_T "\r\n", expected_size);
result = Curl_client_write(data, CLIENTWRITE_BOTH, buf, 0);
if(result)
return result;
result = Curl_client_write(data, CLIENTWRITE_BOTH,
(char *)"Accept-ranges: bytes\r\n", 0);
if(result)
return result;
#ifdef HAVE_STRFTIME
if(fstated) {
struct tm *tm;
time_t clock = (time_t)statbuf.st_mtime;
#ifdef HAVE_GMTIME_R
struct tm buffer;
tm = (struct tm *)gmtime_r(&clock, &buffer);
#else
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);
}
#endif
return result;
}
/* Added by Dolbneff A.V & Spiridonoff A.V */
@ -168,20 +343,21 @@ CURLcode Curl_file(struct connectdata *conn)
/* Is this error code suitable in such situation? */
return CURLE_FTP_BAD_DOWNLOAD_RESUME;
if (expected_size == 0)
if (fstated && (expected_size == 0))
return CURLE_OK;
/* The following is a shortcut implementation of file reading
this is both more efficient than the former call to download() and
it avoids problems with select() and recv() on file descriptors
in Winsock */
if(expected_size != -1)
if(fstated)
Curl_pgrsSetDownloadSize(data, expected_size);
if(conn->resume_from)
/* Added by Dolbneff A.V & Spiridonoff A.V */
lseek(fd, conn->resume_from, SEEK_SET);
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
while (res == CURLE_OK) {
nread = read(fd, buf, BUFSIZE-1);
@ -192,20 +368,18 @@ CURLcode Curl_file(struct connectdata *conn)
break;
bytecount += nread;
/* NOTE: The following call to fwrite does CR/LF translation on
Windows systems if the target is stdout. Use -O or -o parameters
to prevent CR/LF translation (this then goes to a binary mode
file descriptor). */
res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
if(res)
return res;
now = Curl_tvnow();
Curl_pgrsSetDownloadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
else
res = Curl_speedcheck(data, now);
}
now = Curl_tvnow();
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
@ -213,12 +387,4 @@ CURLcode Curl_file(struct connectdata *conn)
return res;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif

View File

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -24,7 +24,8 @@
* $Id$
***************************************************************************/
#ifndef CURL_DISABLE_FILE
CURLcode Curl_file(struct connectdata *conn);
CURLcode Curl_file_connect(struct connectdata *conn);
CURLcode Curl_file(struct connectdata *);
CURLcode Curl_file_done(struct connectdata *, CURLcode);
CURLcode Curl_file_connect(struct connectdata *);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -2,18 +2,18 @@
#define __FORMDATA_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -23,34 +23,43 @@
*
* $Id$
***************************************************************************/
enum formtype {
FORM_DATA, /* regular data */
FORM_FILE /* 'line' points to a file name we should read from */
};
/* plain and simple linked list with lines to send */
struct FormData {
struct FormData *next;
enum formtype type;
char *line;
long length;
size_t length;
};
struct Form {
struct FormData *data; /* current form line to send */
int sent; /* number of bytes of the current line that has already
been sent in a previous invoke */
size_t sent; /* number of bytes of the current line that has
already been sent in a previous invoke */
FILE *fp; /* file to read from */
};
/* used by FormAdd for temporary storage */
typedef struct FormInfo {
char *name;
long namelength;
bool name_alloc;
size_t namelength;
char *value;
long contentslength;
bool value_alloc;
size_t contentslength;
char *contenttype;
bool contenttype_alloc;
long flags;
/* CMC: Added support for buffer uploads */
char *buffer; /* pointer to existing buffer used for file upload */
long bufferlength;
size_t bufferlength;
char *showfilename; /* The file name to show. If not set, the actual
file name will be used */
bool showfilename_alloc;
struct curl_slist* contentheader;
struct FormInfo *more;
} FormInfo;
@ -59,20 +68,21 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata );
CURLcode
Curl_getFormData(struct FormData **,
struct HttpPost *post,
int *size);
struct curl_httppost *post,
curl_off_t *size);
/* fread() emulation */
int Curl_FormReader(char *buffer,
size_t size,
size_t nitems,
FILE *mydata);
size_t Curl_FormReader(char *buffer,
size_t size,
size_t nitems,
FILE *mydata);
/* possible (old) fread() emulation that copies at most one line */
int Curl_FormReadOneLine(char *buffer,
size_t size,
size_t nitems,
FILE *mydata);
/*
* Curl_formpostheader() returns the first line of the formpost, the
* request-header part (which is not part of the request-body like the rest of
* the post).
*/
char *Curl_formpostheader(void *formp, size_t *len);
char *Curl_FormBoundary(void);

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -25,11 +25,11 @@
#ifndef CURL_DISABLE_FTP
CURLcode Curl_ftp(struct connectdata *conn);
CURLcode Curl_ftp_done(struct connectdata *conn);
CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode);
CURLcode Curl_ftp_connect(struct connectdata *conn);
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
CURLcode Curl_GetFTPResponse(int *nread, struct connectdata *conn,
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
int *ftpcode);
CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -35,9 +35,10 @@
#include <unixlib.h>
#endif
#ifdef MALLOCDEBUG
#include <curl/curl.h>
#include "memory.h"
#include "memdebug.h"
#endif
static
char *GetEnv(const char *variable)
@ -53,8 +54,7 @@ char *GetEnv(const char *variable)
#ifdef VMS
char *env = getenv(variable);
if (env && strcmp("HOME",variable) == 0) {
/* VMS does not work because of warning on icc */
/* env = decc$translate_vms(env); */
env = decc$translate_vms(env);
}
#else
/* no length control */
@ -68,11 +68,3 @@ char *curl_getenv(const char *v)
{
return GetEnv(v);
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -26,21 +26,16 @@
#include <curl/curl.h>
#include "urldata.h"
#include "getinfo.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifdef VMS
#include <stdlib.h>
#endif
#include <stdlib.h>
#include "memory.h"
/* Make this the last #include */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#else
#include <stdlib.h>
#endif
/*
* This is supposed to be called in the beginning of a permform() session
@ -103,9 +98,12 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
case CURLINFO_EFFECTIVE_URL:
*param_charp = data->change.url?data->change.url:(char *)"";
break;
case CURLINFO_HTTP_CODE:
case CURLINFO_RESPONSE_CODE:
*param_longp = data->info.httpcode;
break;
case CURLINFO_HTTP_CONNECTCODE:
*param_longp = data->info.httpproxycode;
break;
case CURLINFO_FILETIME:
*param_longp = data->info.filetime;
break;
@ -131,25 +129,25 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
*param_doublep = data->progress.t_starttransfer;
break;
case CURLINFO_SIZE_UPLOAD:
*param_doublep = data->progress.uploaded;
*param_doublep = (double)data->progress.uploaded;
break;
case CURLINFO_SIZE_DOWNLOAD:
*param_doublep = data->progress.downloaded;
*param_doublep = (double)data->progress.downloaded;
break;
case CURLINFO_SPEED_DOWNLOAD:
*param_doublep = data->progress.dlspeed;
*param_doublep = (double)data->progress.dlspeed;
break;
case CURLINFO_SPEED_UPLOAD:
*param_doublep = data->progress.ulspeed;
*param_doublep = (double)data->progress.ulspeed;
break;
case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->set.ssl.certverifyresult;
break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
*param_doublep = data->progress.size_dl;
*param_doublep = (double)data->progress.size_dl;
break;
case CURLINFO_CONTENT_LENGTH_UPLOAD:
*param_doublep = data->progress.size_ul;
*param_doublep = (double)data->progress.size_ul;
break;
case CURLINFO_REDIRECT_TIME:
*param_doublep = data->progress.t_redirect;
@ -161,18 +159,16 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
*param_charp = data->info.contenttype;
break;
case CURLINFO_PRIVATE:
*param_charp = data->set.private?data->set.private:(char *)"";
*param_charp = data->set.private;
break;
case CURLINFO_HTTPAUTH_AVAIL:
*param_longp = data->info.httpauthavail;
break;
case CURLINFO_PROXYAUTH_AVAIL:
*param_longp = data->info.proxyauthavail;
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}
return CURLE_OK;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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

View File

@ -1,236 +0,0 @@
/* ============================================================================
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* Redistribution and use are freely permitted provided that:
*
* 1) This header remain in tact.
* 2) The prototypes for getpass and getpass_r are not changed from:
* char *getpass(const char *prompt)
* char *getpass_r(const char *prompt, char* buffer, int buflen)
* 3) This source code is not used outside of this(getpass.c) file.
* 4) Any changes to this(getpass.c) source code are made publicly available.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* ============================================================================
*
* $Id$
*
* The spirit of this license is to allow use of this source code in any
* project be it open or closed but still encourage the use of the open,
* library based equivilents.
*
* Author(s):
* Angus Mackay <amackay@gus.ml.org>
*
* Contributor(s):
* Daniel Stenberg <daniel@haxx.se>
*/
#include "setup.h" /* setup.h is required for read() prototype */
#ifndef HAVE_GETPASS_R
#ifndef WIN32
#ifdef VMS
#include <stdio.h>
#include <string.h>
#include descrip
#include starlet
#include iodef
#include iosbdef
char *getpass_r(const char *prompt, char *buffer, size_t buflen)
{
long sts;
short chan;
struct _iosb iosb;
/* VMS does not work because of warnings on icc */
/* $DESCRIPTOR(ttdesc, "TT");
buffer[0]='\0';
if ((sts = sys$assign(&ttdesc, &chan,0,0)) & 1) {
if (((sts = sys$qiow(0, chan, IO$_READPROMPT | IO$M_NOECHO, &iosb, 0, 0, buffer, buflen, 0, 0, prompt, strlen(prompt))) & 1) && (iosb.iosb$w_status&1)) {
buffer[iosb.iosb$w_bcnt] = '\0';
}
sts = sys$dassgn(chan);
}
*/
return buffer; /* we always return success */
}
#else /* VMS */
#ifdef HAVE_TERMIOS_H
# if !defined(HAVE_TCGETATTR) && !defined(HAVE_TCSETATTR)
# undef HAVE_TERMIOS_H
# endif
#endif
#ifndef RETSIGTYPE
# define RETSIGTYPE void
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <signal.h>
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#else
# ifdef HAVE_TERMIO_H
# include <termio.h>
# else
# endif
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
char *getpass_r(const char *prompt, char *buffer, size_t buflen)
{
FILE *infp;
char infp_fclose = 0;
FILE *outfp;
RETSIGTYPE (*sigint)();
#ifndef __EMX__
RETSIGTYPE (*sigtstp)();
#endif
size_t bytes_read;
int infd;
int outfd;
#ifdef HAVE_TERMIOS_H
struct termios orig;
struct termios noecho;
#else
# ifdef HAVE_TERMIO_H
struct termio orig;
struct termio noecho;
# else
# endif
#endif
sigint = signal(SIGINT, SIG_IGN);
/* 20000318 mgs
* this is needed by the emx system, SIGTSTP is not a supported signal */
#ifndef __EMX__
sigtstp = signal(SIGTSTP, SIG_IGN);
#endif
infp=fopen("/dev/tty", "r");
if( NULL == infp )
infp = stdin;
else
infp_fclose = 1;
outfp = stderr;
infd = fileno(infp);
outfd = fileno(outfp);
/* dissable echo */
#ifdef HAVE_TERMIOS_H
tcgetattr(outfd, &orig);
noecho = orig;
noecho.c_lflag &= ~ECHO;
tcsetattr(outfd, TCSANOW, &noecho);
#else
# ifdef HAVE_TERMIO_H
ioctl(outfd, TCGETA, &orig);
noecho = orig;
noecho.c_lflag &= ~ECHO;
ioctl(outfd, TCSETA, &noecho);
# else
# endif
#endif
fputs(prompt, outfp);
fflush(outfp);
bytes_read=read(infd, buffer, buflen);
buffer[bytes_read > 0 ? (bytes_read -1) : 0] = '\0';
/* print a new line if needed */
#ifdef HAVE_TERMIOS_H
fputs("\n", outfp);
#else
# ifdef HAVE_TERMIO_H
fputs("\n", outfp);
# else
# endif
#endif
/*
* reset term charectaristics, use TCSAFLUSH incase the
* user types more than buflen
*/
#ifdef HAVE_TERMIOS_H
tcsetattr(outfd, TCSAFLUSH, &orig);
#else
# ifdef HAVE_TERMIO_H
ioctl(outfd, TCSETA, &orig);
# else
# endif
#endif
signal(SIGINT, sigint);
#ifndef __EMX__
signal(SIGTSTP, sigtstp);
#endif
if(infp_fclose)
fclose(infp);
return buffer; /* we always return success */
}
#endif /* VMS */
#else /* WIN32 */
#include <stdio.h>
#include <conio.h>
char *getpass_r(const char *prompt, char *buffer, int buflen)
{
int i;
printf("%s", prompt);
for(i=0; i<buflen; i++) {
buffer[i] = (char)getch();
if ( buffer[i] == '\r' ) {
buffer[i] = 0;
break;
}
}
/* if user didn't hit ENTER, terminate buffer */
if (i==buflen)
buffer[buflen-1]=0;
return buffer; /* we always return success */
}
#endif
#endif /* ifndef HAVE_GETPASS_R */
#if 0
/* for consistensy, here's the old-style function: */
char *getpass(const char *prompt)
{
static char buf[256];
return getpass_r(prompt, buf, sizeof(buf));
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -28,17 +28,13 @@
#include "hash.h"
#include "llist.h"
#include "memory.h"
#ifdef MALLOCDEBUG
/* this must be the last include file */
#include "memdebug.h"
#endif
/* {{{ static unsigned long _hash_str (const char *, size_t)
*/
static unsigned long
_hash_str (const char *key, size_t key_length)
hash_str(const char *key, size_t key_length)
{
char *end = (char *) key + key_length;
unsigned long h = 5381;
@ -50,12 +46,9 @@ _hash_str (const char *key, size_t key_length)
return h;
}
/* }}} */
/* {{{ static void _hash_element_dtor (void *, void *)
*/
static void
_hash_element_dtor (void *user, void *element)
static void
hash_element_dtor(void *user, void *element)
{
curl_hash *h = (curl_hash *) user;
curl_hash_element *e = (curl_hash_element *) element;
@ -68,49 +61,55 @@ _hash_element_dtor (void *user, void *element)
free(e);
}
/* }}} */
/* {{{ void curl_hash_init (curl_hash *, int, curl_hash_dtor)
*/
void
Curl_hash_init (curl_hash *h, int slots, curl_hash_dtor dtor)
/* return 1 on error, 0 is fine */
int
Curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor)
{
int i;
h->dtor = dtor;
h->size = 0;
h->slots = slots;
h->slots = slots;
h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *));
for (i = 0; i < slots; ++i) {
h->table[i] = Curl_llist_alloc((curl_llist_dtor) _hash_element_dtor);
if(h->table) {
for (i = 0; i < slots; ++i) {
h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
if(!h->table[i]) {
while(i--)
Curl_llist_destroy(h->table[i], NULL);
free(h->table);
return 1; /* failure */
}
}
return 0; /* fine */
}
else
return 1; /* failure */
}
/* }}} */
/* {{{ curl_hash *curl_hash_alloc (int, curl_hash_dtor)
*/
curl_hash *
Curl_hash_alloc (int slots, curl_hash_dtor dtor)
Curl_hash_alloc(int slots, curl_hash_dtor dtor)
{
curl_hash *h;
h = (curl_hash *) malloc(sizeof(curl_hash));
if (NULL == h)
return NULL;
Curl_hash_init(h, slots, dtor);
if (h) {
if(Curl_hash_init(h, slots, dtor)) {
/* failure */
free(h);
h = NULL;
}
}
return h;
}
/* }}} */
/* {{{ static int _hash_key_compare (char *, size_t, char *, size_t)
*/
static int
_hash_key_compare (char *key1, size_t key1_len, char *key2, size_t key2_len)
static int
hash_key_compare(char *key1, size_t key1_len, char *key2, size_t key2_len)
{
if (key1_len == key2_len &&
if (key1_len == key2_len &&
*key1 == *key2 &&
memcmp(key1, key2, key1_len) == 0) {
return 1;
@ -118,108 +117,90 @@ _hash_key_compare (char *key1, size_t key1_len, char *key2, size_t key2_len)
return 0;
}
/* }}} */
/* {{{ static int _mk_hash_element (curl_hash_element **, char *, size_t, const void *)
*/
static int
_mk_hash_element (curl_hash_element **e, char *key, size_t key_len, const void *p)
static curl_hash_element *
mk_hash_element(char *key, size_t key_len, const void *p)
{
*e = (curl_hash_element *) malloc(sizeof(curl_hash_element));
(*e)->key = strdup(key);
(*e)->key_len = key_len;
(*e)->ptr = (void *) p;
return 0;
}
/* }}} */
curl_hash_element *he =
(curl_hash_element *) malloc(sizeof(curl_hash_element));
#define find_slot(__h, __k, __k_len) (_hash_str(__k, __k_len) % (__h)->slots)
#define FETCH_LIST \
curl_llist *l = h->table[find_slot(h, key, key_len)]
/* {{{ int curl_hash_add (curl_hash *, char *, size_t, const void *)
*/
int
Curl_hash_add (curl_hash *h, char *key, size_t key_len, const void *p)
{
curl_hash_element *he;
curl_llist_element *le;
FETCH_LIST;
for (le = CURL_LLIST_HEAD(l);
le != NULL;
le = CURL_LLIST_NEXT(le)) {
he = (curl_hash_element *) CURL_LLIST_VALP(le);
if (_hash_key_compare(he->key, he->key_len, key, key_len)) {
h->dtor(he->ptr);
if(he) {
char *dup = strdup(key);
if(dup) {
he->key = dup;
he->key_len = key_len;
he->ptr = (void *) p;
return 1;
}
else {
/* failed to duplicate the key, free memory and fail */
free(he);
he = NULL;
}
}
if (_mk_hash_element(&he, key, key_len, p) != 0)
return 0;
if (Curl_llist_insert_next(l, CURL_LLIST_TAIL(l), he)) {
++h->size;
return 1;
}
return 0;
return he;
}
/* }}} */
/* {{{ int curl_hash_delete (curl_hash *, char *, size_t)
*/
int
Curl_hash_delete(curl_hash *h, char *key, size_t key_len)
#define find_slot(__h, __k, __k_len) (hash_str(__k, __k_len) % (__h)->slots)
#define FETCH_LIST(x,y,z) x->table[find_slot(x, y, z)]
/* Return the data in the hash. If there already was a match in the hash,
that data is returned. */
void *
Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p)
{
curl_hash_element *he;
curl_llist_element *le;
FETCH_LIST;
curl_llist *l = FETCH_LIST(h, key, key_len);
for (le = CURL_LLIST_HEAD(l);
le != NULL;
le = CURL_LLIST_NEXT(le)) {
he = CURL_LLIST_VALP(le);
if (_hash_key_compare(he->key, he->key_len, key, key_len)) {
Curl_llist_remove(l, le, (void *) h);
--h->size;
return 1;
for (le = l->head; le; le = le->next) {
he = (curl_hash_element *) le->ptr;
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
h->dtor(p); /* remove the NEW entry */
return he->ptr; /* return the EXISTING entry */
}
}
return 0;
}
/* }}} */
he = mk_hash_element(key, key_len, p);
if (he) {
if(Curl_llist_insert_next(l, l->tail, he)) {
++h->size;
return p; /* return the new entry */
}
/*
* Couldn't insert it, destroy the 'he' element and the key again. We
* don't call hash_element_dtor() since that would also call the
* "destructor" for the actual data 'p'. When we fail, we shall not touch
* that data.
*/
free(he->key);
free(he);
}
return NULL; /* failure */
}
/* {{{ int curl_hash_pick (curl_hash *, char *, size_t, void **)
*/
void *
Curl_hash_pick(curl_hash *h, char *key, size_t key_len)
{
curl_llist_element *le;
curl_hash_element *he;
FETCH_LIST;
curl_llist *l = FETCH_LIST(h, key, key_len);
for (le = CURL_LLIST_HEAD(l);
le != NULL;
le = CURL_LLIST_NEXT(le)) {
he = CURL_LLIST_VALP(le);
if (_hash_key_compare(he->key, he->key_len, key, key_len)) {
for (le = l->head;
le;
le = le->next) {
he = le->ptr;
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
return he->ptr;
}
}
return NULL;
}
/* }}} */
/* {{{ void curl_hash_apply (curl_hash *, void *, void (*)(void *, curl_hash_element *))
*/
void
#if defined(CURLDEBUG) && defined(AGGRESIVE_TEST)
void
Curl_hash_apply(curl_hash *h, void *user,
void (*cb)(void *user, void *ptr))
{
@ -227,18 +208,16 @@ Curl_hash_apply(curl_hash *h, void *user,
int i;
for (i = 0; i < h->slots; ++i) {
for (le = CURL_LLIST_HEAD(h->table[i]);
le != NULL;
le = CURL_LLIST_NEXT(le)) {
curl_hash_element *el = CURL_LLIST_VALP(le);
for (le = (h->table[i])->head;
le;
le = le->next) {
curl_hash_element *el = le->ptr;
cb(user, el->ptr);
}
}
}
/* }}} */
#endif
/* {{{ void curl_hash_clean (curl_hash *)
*/
void
Curl_hash_clean(curl_hash *h)
{
@ -250,45 +229,33 @@ Curl_hash_clean(curl_hash *h)
free(h->table);
}
/* }}} */
/* {{{ void curl_hash_clean_with_criterium (curl_hash *, void *,
int (*)(void *, void *))
*/
void
Curl_hash_clean_with_criterium(curl_hash *h, void *user,
int (*comp)(void *, void *))
{
curl_llist_element *le;
curl_llist_element *lnext;
curl_llist *list;
int i;
for (i = 0; i < h->slots; ++i) {
le = CURL_LLIST_HEAD(h->table[i]);
while(le != NULL)
if (comp(user, ((curl_hash_element *) CURL_LLIST_VALP(le))->ptr)) {
lnext = CURL_LLIST_NEXT(le);
Curl_llist_remove(h->table[i], le, (void *) h);
--h->size;
le = lnext;
list = h->table[i];
le = list->head; /* get first list entry */
while(le) {
curl_hash_element *he = le->ptr;
lnext = le->next;
/* ask the callback function if we shall remove this entry or not */
if (comp(user, he->ptr)) {
Curl_llist_remove(list, le, (void *) h);
--h->size; /* one less entry in the hash now */
}
else
le = CURL_LLIST_NEXT(le);
le = lnext;
}
}
}
/* {{{ int curl_hash_count (curl_hash *)
*/
int
Curl_hash_count(curl_hash *h)
{
return (int)h->size;
}
/* }}} */
/* {{{ void curl_hash_destroy (curl_hash *)
*/
void
void
Curl_hash_destroy(curl_hash *h)
{
if (!h)
@ -297,12 +264,4 @@ Curl_hash_destroy(curl_hash *h)
Curl_hash_clean(h);
free(h);
}
/* }}} */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -1,18 +1,18 @@
#ifndef __HASH_H
#define __HASH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -45,9 +45,9 @@ typedef struct _curl_hash_element {
} curl_hash_element;
void Curl_hash_init(curl_hash *, int, curl_hash_dtor);
int Curl_hash_init(curl_hash *, int, curl_hash_dtor);
curl_hash *Curl_hash_alloc(int, curl_hash_dtor);
int Curl_hash_add(curl_hash *, char *, size_t, const void *);
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,
@ -58,11 +58,3 @@ void Curl_hash_clean_with_criterium(curl_hash *h, void *user, int (*comp)(void *
void Curl_hash_destroy(curl_hash *h);
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

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

View File

@ -0,0 +1,170 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for builds using asynchronous name resolves
**********************************************************************/
#ifdef CURLRES_ASYNCH
/*
* addrinfo_callback() gets called by ares, gethostbyname_thread() or
* getaddrinfo_thread() when we got the name resolved (or not!).
*
* If the status argument is CURL_ASYNC_SUCCESS, we might need to copy the
* address field since it might be freed when this function returns. This
* operation stores the resolved data in the DNS cache.
*
* NOTE: for IPv6 operations, Curl_addrinfo_copy() returns the same
* pointer it is given as argument!
*
* The storage operation locks and unlocks the DNS cache.
*/
static void addrinfo_callback(void *arg, /* "struct connectdata *" */
int status,
void *addr)
{
struct connectdata *conn = (struct connectdata *)arg;
struct Curl_dns_entry *dns = NULL;
conn->async.done = TRUE;
conn->async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
/*
* IPv4: Curl_addrinfo_copy() copies the address and returns an allocated
* version.
*
* IPv6: Curl_addrinfo_copy() returns the input pointer!
*/
Curl_addrinfo *ai = Curl_addrinfo_copy(addr, conn->async.port);
if(ai) {
struct SessionHandle *data = conn->data;
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
conn->async.hostname,
conn->async.port);
if(!dns)
/* failed to store, cleanup and return error */
Curl_freeaddrinfo(ai);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
}
conn->async.dns = dns;
/* ipv4: The input hostent struct will be freed by ares when we return from
this function */
}
void Curl_addrinfo4_callback(void *arg, /* "struct connectdata *" */
int status,
struct hostent *hostent)
{
addrinfo_callback(arg, status, hostent);
}
#ifdef CURLRES_IPV6
void Curl_addrinfo6_callback(void *arg, /* "struct connectdata *" */
int status,
struct addrinfo *ai)
{
addrinfo_callback(arg, status, ai);
}
#endif
#endif /* CURLRES_ASYNC */

File diff suppressed because it is too large Load Diff

View File

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

449
Source/CTest/Curl/hostip4.c Normal file
View File

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

263
Source/CTest/Curl/hostip6.c Normal file
View File

@ -0,0 +1,263 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for ipv6-enabled builds
**********************************************************************/
#ifdef CURLRES_IPV6
/*
* This is a wrapper function for freeing name information in a protocol
* independent way. This takes care of using the appropriate underlaying
* function.
*/
void Curl_freeaddrinfo(Curl_addrinfo *p)
{
freeaddrinfo(p);
}
#ifdef CURLRES_ASYNCH
/*
* Curl_addrinfo_copy() is used by the asynch callback to copy a given
* address. But this is an ipv6 build and then we don't copy the address, we
* just return the same pointer!
*/
Curl_addrinfo *Curl_addrinfo_copy(void *source, int port)
{
(void) port;
return source;
}
#endif
#ifdef CURLDEBUG
/* These are strictly for memory tracing and are using the same style as the
* family otherwise present in memdebug.c. I put these ones here since they
* require a bunch of structs I didn't wanna include in memdebug.c
*/
int curl_dogetaddrinfo(char *hostname, char *service,
struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source)
{
int res=(getaddrinfo)(hostname, service, hints, result);
if(0 == res) {
/* success */
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
source, line, (void *)*result);
}
else {
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
source, line);
}
return res;
}
int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags,
int line, const char *source)
{
int res=(getnameinfo)(sa, salen, host, hostlen, serv, servlen, flags);
if(0 == res) {
/* success */
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo()\n",
source, line);
}
else {
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo() failed = %d\n",
source, line, res);
}
return res;
}
void curl_dofreeaddrinfo(struct addrinfo *freethis,
int line, const char *source)
{
(freeaddrinfo)(freethis);
if(logfile)
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
source, line, (void *)freethis);
}
#endif
/*
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
bool Curl_ipvalid(struct SessionHandle *data)
{
if(data->set.ip_version == CURL_IPRESOLVE_V6) {
/* see if we have an IPv6 stack */
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s == CURL_SOCKET_BAD)
/* an ipv6 address was requested and we can't get/use one */
return FALSE;
sclose(s);
}
return TRUE;
}
#ifndef USE_THREADING_GETADDRINFO
/*
* Curl_getaddrinfo() when built ipv6-enabled (non-threading version).
*
* Returns name information about the given hostname and port number. If
* successful, the 'addrinfo' is returned and the forth argument will point to
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char *hostname,
int port,
int *waitp)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
curl_socket_t s;
int pf;
struct SessionHandle *data = conn->data;
*waitp=0; /* don't wait, we have the response now */
/* see if we have an IPv6 stack */
s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s < 0) {
/* Some non-IPv6 stacks have been found to make very slow name resolves
* when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
* the stack seems to be a non-ipv6 one. */
pf = PF_INET;
}
else {
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
* possible checks. And close the socket again.
*/
sclose(s);
/*
* Check if a more limited name resolve has been requested.
*/
switch(data->set.ip_version) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
case CURL_IPRESOLVE_V6:
pf = PF_INET6;
break;
default:
pf = PF_UNSPEC;
break;
}
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
snprintf(sbuf, sizeof(sbuf), "%d", port);
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
return NULL;
}
return res;
}
#endif /* USE_THREADING_GETADDRINFO */
#endif /* ipv6 */

149
Source/CTest/Curl/hostsyn.c Normal file
View File

@ -0,0 +1,149 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#include <string.h>
#include <errno.h>
#define _REENTRANT
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <malloc.h>
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for free() prototypes */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for the close() proto */
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef WIN32
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/***********************************************************************
* Only for builds using synchronous name resolves
**********************************************************************/
#ifdef CURLRES_SYNCH
/*
* Curl_wait_for_resolv() for synch-builds. Curl_resolv() can never return
* wait==TRUE, so this function will never be called. If it still gets called,
* we return failure at once.
*
* We provide this function only to allow multi.c to remain unaware if we are
* doing asynch resolves or not.
*/
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
(void)conn;
*entry=NULL;
return CURLE_COULDNT_RESOLVE_HOST;
}
/*
* This function will never be called when synch-built. If it still gets
* called, we return failure at once.
*
* We provide this function only to allow multi.c to remain unaware if we are
* doing asynch resolves or not.
*/
CURLcode Curl_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns)
{
(void)conn;
*dns = NULL;
return CURLE_COULDNT_RESOLVE_HOST;
}
/*
* We just return OK, this function is never actually used for synch builds.
* It is present here to keep #ifdefs out from multi.c
*/
CURLcode Curl_fdset(struct connectdata *conn,
fd_set *read_fd_set,
fd_set *write_fd_set,
int *max_fdp)
{
(void)conn;
(void)read_fd_set;
(void)write_fd_set;
(void)max_fdp;
return CURLE_OK;
}
#endif /* truly sync */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -2,18 +2,18 @@
#define __HTTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -35,12 +35,27 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
/* protocol-specific functions set up to be called by the main engine */
CURLcode Curl_http(struct connectdata *conn);
CURLcode Curl_http_done(struct connectdata *conn);
CURLcode Curl_http_done(struct connectdata *, CURLcode);
CURLcode Curl_http_connect(struct connectdata *conn);
/* The following functions are defined in http_chunks.c */
void Curl_httpchunk_init(struct connectdata *conn);
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
ssize_t length, ssize_t *wrote);
/* These functions are in http.c */
void Curl_http_auth_stage(struct SessionHandle *data, int stage);
CURLcode Curl_http_input_auth(struct connectdata *conn,
int httpcode, char *header);
CURLcode Curl_http_auth_act(struct connectdata *conn);
int Curl_http_should_fail(struct connectdata *conn);
/* If only the PICKNONE bit is set, there has been a round-trip and we
selected to use no auth at all. Ie, we actively select no auth, as opposed
to not having one selected. The other CURLAUTH_* defines are present in the
public curl/curl.h header. */
#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */
#endif
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -33,15 +33,15 @@
#include "urldata.h" /* it includes http_chunks.h */
#include "sendf.h" /* for the client write stuff */
#include "content_encoding.h" /* 08/29/02 jhrg */
#include "content_encoding.h"
#include "http.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/*
* Chunk format (simplified):
@ -99,13 +99,17 @@ void Curl_httpchunk_init(struct connectdata *conn)
*/
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
char *datap,
size_t length,
size_t *wrote)
ssize_t datalen,
ssize_t *wrotep)
{
CURLcode result;
CURLcode result=CURLE_OK;
struct Curl_chunker *ch = &conn->proto.http->chunk;
int piece;
*wrote = 0; /* nothing yet */
struct Curl_transfer_keeper *k = &conn->keep;
size_t piece;
size_t length = (size_t)datalen;
size_t *wrote = (size_t *)wrotep;
*wrote = 0; /* nothing's written yet */
while(length) {
switch(ch->state) {
@ -171,30 +175,38 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
We expect another 'datasize' of data. We have 'length' right now,
it can be more or less than 'datasize'. Get the smallest piece.
*/
piece = (int)((ch->datasize >= length)?length:ch->datasize);
piece = (ch->datasize >= length)?length:ch->datasize;
/* Write the data portion available */
/* Added content-encoding here; untested but almost identical to the
tested code in transfer.c. 08/29/02 jhrg */
#ifdef HAVE_LIBZ
switch (conn->keep.content_encoding) {
case IDENTITY:
#endif
result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap,
piece);
if(!k->ignorebody)
result = Curl_client_write(conn->data, CLIENTWRITE_BODY, datap,
piece);
#ifdef HAVE_LIBZ
break;
case DEFLATE:
result = Curl_unencode_deflate_write(conn->data, &conn->keep, piece);
/* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap;
result = Curl_unencode_deflate_write(conn->data, &conn->keep,
(ssize_t)piece);
break;
case GZIP:
/* update conn->keep.str to point to the chunk data. */
conn->keep.str = datap;
result = Curl_unencode_gzip_write(conn->data, &conn->keep,
(ssize_t)piece);
break;
case COMPRESS:
default:
failf (conn->data,
"Unrecognized content encoding type. "
"libcurl understands `identity' and `deflate' "
"libcurl understands `identity', `deflate' and `gzip' "
"content encodings.");
return CHUNKE_BAD_ENCODING;
}
@ -202,6 +214,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
if(result)
return CHUNKE_WRITE_ERROR;
*wrote += piece;
ch->datasize -= piece; /* decrease amount left to expect */
@ -248,12 +261,4 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
}
return CHUNKE_OK;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
#endif /* CURL_DISABLE_HTTP */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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

View File

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

View File

@ -0,0 +1,53 @@
#ifndef __HTTP_DIGEST_H
#define __HTTP_DIGEST_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
typedef enum {
CURLDIGEST_NONE, /* not a digest */
CURLDIGEST_BAD, /* a digest, but one we don't like */
CURLDIGEST_BADALGO, /* unsupported algorithm requested */
CURLDIGEST_NOMEM,
CURLDIGEST_FINE, /* a digest we act on */
CURLDIGEST_LAST /* last entry in this enum, don't use */
} CURLdigest;
enum {
CURLDIGESTALGO_MD5,
CURLDIGESTALGO_MD5SESS
};
/* this is for digest header input */
CURLdigest Curl_input_digest(struct connectdata *conn,
bool proxy, char *header);
/* this is for creating digest header output */
CURLcode Curl_output_digest(struct connectdata *conn,
bool proxy,
unsigned char *request,
unsigned char *uripath);
void Curl_digest_cleanup(struct SessionHandle *data);
void Curl_digest_cleanup_one(struct digestdata *dig);
#endif

View File

@ -0,0 +1,332 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#ifdef HAVE_GSSAPI
#ifdef HAVE_GSSMIT
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
#endif
#ifndef CURL_DISABLE_HTTP
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "base64.h"
#include "http_negotiate.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#include "memdebug.h"
static int
get_gss_name(struct connectdata *conn, gss_name_t *server)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 major_status, minor_status;
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
char name[2048];
const char* service;
/* GSSAPI implementation by Globus (known as GSI) requires the name to be
of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
Change following lines if you want to use GSI */
/* IIS uses the <service>@<fqdn> form but uses 'http' as the service name */
if (neg_ctx->gss)
service = "KHTTP";
else
service = "HTTP";
token.length = strlen(service) + 1 + strlen(conn->host.name) + 1;
if (token.length + 1 > sizeof(name))
return EMSGSIZE;
snprintf(name, sizeof(name), "%s@%s", service, conn->host.name);
token.value = (void *) name;
major_status = gss_import_name(&minor_status,
&token,
GSS_C_NT_HOSTBASED_SERVICE,
server);
return GSS_ERROR(major_status) ? -1 : 0;
}
static void
log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix)
{
OM_uint32 maj_stat, min_stat;
OM_uint32 msg_ctx = 0;
gss_buffer_desc status_string;
char buf[1024];
size_t len;
snprintf(buf, sizeof(buf), "%s", prefix);
len = strlen(buf);
do {
maj_stat = gss_display_status (&min_stat,
error_status,
GSS_C_MECH_CODE,
GSS_C_NO_OID,
&msg_ctx,
&status_string);
if (sizeof(buf) > len + status_string.length + 1) {
snprintf(buf + len, sizeof(buf) - len,
": %s", (char*) status_string.value);
len += status_string.length;
}
gss_release_buffer(&min_stat, &status_string);
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
infof(conn->data, buf);
}
int Curl_input_negotiate(struct connectdata *conn, char *header)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 major_status, minor_status, minor_status2;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
int ret;
size_t len;
bool gss;
const char* protocol;
while(*header && isspace((int)*header))
header++;
if(checkprefix("GSS-Negotiate", header)) {
protocol = "GSS-Negotiate";
gss = TRUE;
}
else if (checkprefix("Negotiate", header)) {
protocol = "Negotiate";
gss = FALSE;
}
else
return -1;
if (neg_ctx->context) {
if (neg_ctx->gss != gss) {
return -1;
}
}
else {
neg_ctx->protocol = protocol;
neg_ctx->gss = gss;
}
if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
/* We finished succesfully our part of authentication, but server
* rejected it (since we're again here). Exit with an error since we
* can't invent anything better */
Curl_cleanup_negotiate(conn->data);
return -1;
}
if (neg_ctx->server_name == NULL &&
(ret = get_gss_name(conn, &neg_ctx->server_name)))
return ret;
header += strlen(neg_ctx->protocol);
while(*header && isspace((int)*header))
header++;
len = strlen(header);
if (len > 0) {
int rawlen;
input_token.length = (len+3)/4 * 3;
input_token.value = malloc(input_token.length);
if (input_token.value == NULL)
return ENOMEM;
rawlen = Curl_base64_decode(header, input_token.value);
if (rawlen < 0)
return -1;
input_token.length = rawlen;
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
if (checkprefix("Negotiate", header)) {
ASN1_OBJECT * object = NULL;
int rc = 1;
unsigned char * spnegoToken = NULL;
size_t spnegoTokenLength = 0;
unsigned char * mechToken = NULL;
size_t mechTokenLength = 0;
spnegoToken = malloc(input_token.length);
if (input_token.value == NULL)
return ENOMEM;
spnegoTokenLength = input_token.length;
object = OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
if (!parseSpnegoTargetToken(spnegoToken,
spnegoTokenLength,
NULL,
NULL,
&mechToken,
&mechTokenLength,
NULL,
NULL)) {
free(spnegoToken);
spnegoToken = NULL;
infof(conn->data, "Parse SPNEGO Target Token failed\n");
}
else {
free(input_token.value);
input_token.value = NULL;
input_token.value = malloc(mechTokenLength);
memcpy(input_token.value, mechToken,mechTokenLength);
input_token.length = mechTokenLength;
free(mechToken);
mechToken = NULL;
infof(conn->data, "Parse SPNEGO Target Token succeded\n");
}
}
#endif
}
major_status = gss_init_sec_context(&minor_status,
GSS_C_NO_CREDENTIAL,
&neg_ctx->context,
neg_ctx->server_name,
GSS_C_NO_OID,
GSS_C_DELEG_FLAG,
0,
GSS_C_NO_CHANNEL_BINDINGS,
&input_token,
NULL,
&output_token,
NULL,
NULL);
if (input_token.length > 0)
gss_release_buffer(&minor_status2, &input_token);
neg_ctx->status = major_status;
if (GSS_ERROR(major_status)) {
/* Curl_cleanup_negotiate(conn->data) ??? */
log_gss_error(conn, minor_status,
(char *)"gss_init_sec_context() failed: ");
return -1;
}
if (output_token.length == 0) {
return -1;
}
neg_ctx->output_token = output_token;
/* conn->bits.close = FALSE; */
return 0;
}
CURLcode Curl_output_negotiate(struct connectdata *conn)
{
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
OM_uint32 minor_status;
char *encoded = NULL;
int len;
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
if (checkprefix("Negotiate",neg_ctx->protocol)) {
ASN1_OBJECT * object = NULL;
int rc = 1;
unsigned char * spnegoToken = NULL;
size_t spnegoTokenLength = 0;
unsigned char * responseToken = NULL;
size_t responseTokenLength = 0;
responseToken = malloc(neg_ctx->output_token.length);
if ( responseToken == NULL)
return CURLE_OUT_OF_MEMORY;
memcpy(responseToken, neg_ctx->output_token.value,
neg_ctx->output_token.length);
responseTokenLength = neg_ctx->output_token.length;
object=OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
if (!makeSpnegoInitialToken (object,
responseToken,
responseTokenLength,
&spnegoToken,
&spnegoTokenLength)) {
free(responseToken);
responseToken = NULL;
infof(conn->data, "Make SPNEGO Initial Token failed\n");
}
else {
free(neg_ctx->output_token.value);
responseToken = NULL;
neg_ctx->output_token.value = malloc(spnegoTokenLength);
memcpy(neg_ctx->output_token.value, spnegoToken,spnegoTokenLength);
neg_ctx->output_token.length = spnegoTokenLength;
free(spnegoToken);
spnegoToken = NULL;
infof(conn->data, "Make SPNEGO Initial Token succeded\n");
}
}
#endif
len = Curl_base64_encode(neg_ctx->output_token.value,
neg_ctx->output_token.length,
&encoded);
if (len < 0)
return CURLE_OUT_OF_MEMORY;
conn->allocptr.userpwd =
aprintf("Authorization: %s %s\r\n", neg_ctx->protocol, encoded);
free(encoded);
gss_release_buffer(&minor_status, &neg_ctx->output_token);
return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
}
void Curl_cleanup_negotiate(struct SessionHandle *data)
{
OM_uint32 minor_status;
struct negotiatedata *neg_ctx = &data->state.negotiate;
if (neg_ctx->context != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
if (neg_ctx->output_token.length != 0)
gss_release_buffer(&minor_status, &neg_ctx->output_token);
if (neg_ctx->server_name != GSS_C_NO_NAME)
gss_release_name(&minor_status, &neg_ctx->server_name);
memset(neg_ctx, 0, sizeof(*neg_ctx));
}
#endif
#endif

View File

@ -0,0 +1,39 @@
#ifndef __HTTP_NEGOTIATE_H
#define __HTTP_NEGOTIATE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#ifdef HAVE_GSSAPI
/* this is for Negotiate header input */
int Curl_input_negotiate(struct connectdata *conn, char *header);
/* this is for creating Negotiate header output */
CURLcode Curl_output_negotiate(struct connectdata *conn);
void Curl_cleanup_negotiate(struct SessionHandle *data);
#endif
#endif

View File

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

View File

@ -0,0 +1,143 @@
#ifndef __HTTP_NTLM_H
#define __HTTP_NTLM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
typedef enum {
CURLNTLM_NONE, /* not a ntlm */
CURLNTLM_BAD, /* an ntlm, but one we don't like */
CURLNTLM_FIRST, /* the first 401-reply we got with NTLM */
CURLNTLM_FINE, /* an ntlm we act on */
CURLNTLM_LAST /* last entry in this enum, don't use */
} CURLntlm;
/* this is for ntlm header input */
CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, char *header);
/* this is for creating ntlm header output */
CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
void Curl_ntlm_cleanup(struct SessionHandle *data);
/* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
/* Indicates that Unicode strings are supported for use in security buffer
data. */
#define NTLMFLAG_NEGOTIATE_OEM (1<<1)
/* Indicates that OEM strings are supported for use in security buffer data. */
#define NTLMFLAG_REQUEST_TARGET (1<<2)
/* Requests that the server's authentication realm be included in the Type 2
message. */
/* unknown (1<<3) */
#define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
/* Specifies that authenticated communication between the client and server
should carry a digital signature (message integrity). */
#define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
/* Specifies that authenticated communication between the client and server
should be encrypted (message confidentiality). */
#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
/* Indicates that the LAN Manager session key should be used for signing and
sealing authenticated communications. */
#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
/* Indicates that NTLM authentication is being used. */
/* unknown (1<<10) */
/* unknown (1<<11) */
#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
/* Sent by the client in the Type 1 message to indicate that a desired
authentication realm is included in the message. */
#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
/* Sent by the client in the Type 1 message to indicate that the client
workstation's name is included in the message. */
#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
/* Sent by the server to indicate that the server and client are on the same
machine. Implies that the client may use a pre-established local security
context rather than responding to the challenge. */
#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
/* Indicates that authenticated communication between the client and server
should be signed with a "dummy" signature. */
#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a domain. */
#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a server. */
#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
/* Sent by the server in the Type 2 message to indicate that the target
authentication realm is a share. Presumably, this is for share-level
authentication. Usage is unclear. */
#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
/* Indicates that the NTLM2 signing and sealing scheme should be used for
protecting authenticated communications. */
#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
/* unknown purpose */
#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
/* unknown purpose */
#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
/* Sent by the server in the Type 2 message to indicate that it is including a
Target Information block in the message. */
/* unknown (1<24) */
/* unknown (1<25) */
/* unknown (1<26) */
/* unknown (1<27) */
/* unknown (1<28) */
#define NTLMFLAG_NEGOTIATE_128 (1<<29)
/* Indicates that 128-bit encryption is supported. */
#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
/* unknown purpose */
#define NTLMFLAG_NEGOTIATE_56 (1<<31)
/* Indicates that 56-bit encryption is supported. */
#endif

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -27,12 +27,12 @@
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if ! defined(WIN32) && ! defined(__BEOS__) && !defined(__CYGWIN32__)
#if !defined(WIN32) && !defined(__BEOS__) && !defined(__CYGWIN32__) && \
!defined(__riscos__) && !defined(__INTERIX) && !defined(NETWARE)
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@ -51,7 +51,9 @@
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
/* -- if2ip() -- */
#ifdef HAVE_NETDB_H
@ -62,27 +64,27 @@
#include <sys/sockio.h>
#endif
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#ifdef VMS
#define IOCTL_3_ARGS
#include <inet.h>
#endif
#include "if2ip.h"
#include "memory.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#define SYS_ERROR -1
char *Curl_if2ip(char *interface, char *buf, int buf_size)
char *Curl_if2ip(const char *interface, char *buf, int buf_size)
{
int dummy;
char *ip=NULL;
if(!interface)
return NULL;
@ -92,8 +94,11 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
}
else {
struct ifreq req;
size_t len = strlen(interface);
memset(&req, 0, sizeof(req));
strcpy(req.ifr_name, interface);
if(len >= sizeof(req.ifr_name))
return NULL; /* this can't be a fine interface name */
memcpy(req.ifr_name, interface, len+1);
req.ifr_addr.sa_family = AF_INET;
#ifdef IOCTL_3_ARGS
if (SYS_ERROR == ioctl(dummy, SIOCGIFADDR, &req)) {
@ -106,9 +111,7 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
else {
struct in_addr in;
struct sockaddr_in *s;
struct sockaddr *sadd = &req.ifr_dstaddr;
memcpy(&s, &sadd, sizeof(struct sockaddr_in*));
struct sockaddr_in *s = (struct sockaddr_in *)&req.ifr_dstaddr;
memcpy(&in, &(s->sin_addr.s_addr), sizeof(in));
#if defined(HAVE_INET_NTOA_R)
ip = inet_ntoa_r(in,buf,buf_size);
@ -124,13 +127,11 @@ char *Curl_if2ip(char *interface, char *buf, int buf_size)
/* -- end of if2ip() -- */
#else
#define if2ip(x) NULL
char *Curl_if2ip(const char *interface, char *buf, int buf_size)
{
(void) interface;
(void) buf;
(void) buf_size;
return NULL;
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -1,18 +1,18 @@
#ifndef __IF2IP_H
#define __IF2IP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -24,8 +24,9 @@
***************************************************************************/
#include "setup.h"
#if ! defined(WIN32) && ! defined(__BEOS__) && !defined(__CYGWIN32__)
extern char *Curl_if2ip(char *interface, char *buf, int buf_size);
#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
@ -62,7 +63,7 @@ struct ifreq {
#define ifr_metric ifr_ifru.ifru_metric /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
#endif /* interix */
#endif

View File

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

View File

@ -0,0 +1,37 @@
#ifndef __INET_NTOP_H
#define __INET_NTOP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#ifdef HAVE_INET_NTOP
#define Curl_inet_ntop(af,addr,buf,size) inet_ntop(af,addr,buf,size)
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#else
const char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size);
#endif
#endif /* __INET_NTOP_H */

View File

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

View File

@ -1,5 +1,5 @@
#ifndef __GETPASS_H
#define __GETPASS_H
#ifndef __INET_PTON_H
#define __INET_PTON_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -22,14 +22,16 @@
*
* $Id$
***************************************************************************/
#ifndef HAVE_GETPASS_R
/* If there's a system-provided function named like this, we trust it is
also found in one of the standard headers. */
/*
* Returning NULL will abort the continued operation!
*/
char* getpass_r(const char *prompt, char* buffer, size_t buflen );
#include "setup.h"
#ifdef HAVE_INET_PTON
#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#else
int Curl_inet_pton(int, const char *, void *);
#endif
#endif
#endif /* __INET_PTON_H */

View File

@ -10,22 +10,22 @@
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@ -41,15 +41,17 @@
#include "setup.h"
#ifndef CURL_DISABLE_FTP
#ifdef KRB4
#ifdef HAVE_KRB4
#include "security.h"
#include "base64.h"
#include <stdlib.h>
#ifdef HAVE_NETDB_H
#include <netdb.h>
#include <syslog.h>
#endif
#include <string.h>
#include <krb.h>
#include <des.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for getpid() */
@ -57,27 +59,27 @@
#include "ftp.h"
#include "sendf.h"
#include "krb4.h"
#include "memory.h"
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#define LOCAL_ADDR (&conn->local_addr)
#define REMOTE_ADDR (&conn->serv_addr)
#define REMOTE_ADDR conn->ip_addr->ai_addr
#define myctladdr LOCAL_ADDR
#define hisctladdr REMOTE_ADDR
struct krb4_data {
des_cblock key;
des_key_schedule schedule;
char name[ANAME_SZ];
char instance[INST_SZ];
char realm[REALM_SZ];
des_cblock key;
des_key_schedule schedule;
char name[ANAME_SZ];
char instance[INST_SZ];
char realm[REALM_SZ];
};
#ifndef HAVE_STRLCPY
@ -85,18 +87,18 @@ struct krb4_data {
static size_t
strlcpy (char *dst, const char *src, size_t dst_sz)
{
size_t n;
char *p;
size_t n;
char *p;
for (p = dst, n = 0;
n + 1 < dst_sz && *src != '\0';
++p, ++src, ++n)
*p = *src;
*p = '\0';
if (*src == '\0')
return n;
else
return n + strlen (src);
for (p = dst, n = 0;
n + 1 < dst_sz && *src != '\0';
++p, ++src, ++n)
*p = *src;
*p = '\0';
if (*src == '\0')
return n;
else
return n + strlen (src);
}
#else
size_t strlcpy (char *dst, const char *src, size_t dst_sz);
@ -115,24 +117,25 @@ static int
krb4_decode(void *app_data, void *buf, int len, int level,
struct connectdata *conn)
{
MSG_DAT m;
int e;
struct krb4_data *d = app_data;
if(level == prot_safe)
e = krb_rd_safe(buf, len, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
else
e = krb_rd_priv(buf, len, d->schedule, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
if(e){
syslog(LOG_ERR, "krb4_decode: %s", krb_get_err_text(e));
return -1;
}
memmove(buf, m.app_data, m.app_length);
return m.app_length;
MSG_DAT m;
int e;
struct krb4_data *d = app_data;
if(level == prot_safe)
e = krb_rd_safe(buf, len, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
else
e = krb_rd_priv(buf, len, d->schedule, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
if(e) {
struct SessionHandle *data = conn->data;
infof(data, "krb4_decode: %s\n", krb_get_err_text(e));
return -1;
}
memmove(buf, m.app_data, m.app_length);
return m.app_length;
}
static int
@ -149,44 +152,48 @@ static int
krb4_encode(void *app_data, void *from, int length, int level, void **to,
struct connectdata *conn)
{
struct krb4_data *d = app_data;
*to = malloc(length + 31);
if(level == prot_safe)
return krb_mk_safe(from, *to, length, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else if(level == prot_private)
return krb_mk_priv(from, *to, length, d->schedule, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else
return -1;
struct krb4_data *d = app_data;
*to = malloc(length + 31);
if(level == prot_safe)
return krb_mk_safe(from, *to, length, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else if(level == prot_private)
return krb_mk_priv(from, *to, length, d->schedule, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else
return -1;
}
static int
mk_auth(struct krb4_data *d, KTEXT adat,
mk_auth(struct krb4_data *d, KTEXT adat,
const char *service, char *host, int checksum)
{
int ret;
CREDENTIALS cred;
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
int ret;
CREDENTIALS cred;
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_mk_req(adat, sname, inst, realm, checksum);
if(ret)
return ret;
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_get_cred(sname, inst, realm, &cred);
memmove(&d->key, &cred.session, sizeof(des_cblock));
des_key_sched(&d->key, d->schedule);
memset(&cred, 0, sizeof(cred));
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_mk_req(adat, sname, inst, realm, checksum);
if(ret)
return ret;
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_get_cred(sname, inst, realm, &cred);
memmove(&d->key, &cred.session, sizeof(des_cblock));
des_key_sched(&d->key, d->schedule);
memset(&cred, 0, sizeof(cred));
return ret;
}
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
int krb_get_our_ip_for_realm(char *, struct in_addr *);
#endif
static int
krb4_auth(void *app_data, struct connectdata *conn)
{
@ -198,13 +205,13 @@ krb4_auth(void *app_data, struct connectdata *conn)
int checksum;
u_int32_t cs;
struct krb4_data *d = app_data;
char *host = conn->hostname;
char *host = conn->host.name;
ssize_t nread;
int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
CURLcode result;
if(getsockname(conn->firstsocket,
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
perror("getsockname()");
@ -216,7 +223,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
Curl_infof(data, "%s\n", krb_get_err_text(ret));
return AUTH_CONTINUE;
}
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
if (krb_get_config_bool("nat_in_use")) {
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
@ -242,7 +249,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
}
#endif
if(Curl_base64_encode(adat.dat, adat.length, &p) < 0) {
if(Curl_base64_encode((char *)adat.dat, adat.length, &p) < 1) {
Curl_failf(data, "Out of memory base64-encoding");
return AUTH_CONTINUE;
}
@ -268,17 +275,17 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_ERROR;
}
p += 5;
len = Curl_base64_decode(p, adat.dat);
len = Curl_base64_decode(p, (char *)adat.dat);
if(len < 0) {
Curl_failf(data, "Failed to decode base64 from server");
return AUTH_ERROR;
}
adat.length = len;
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
(struct sockaddr_in *)hisctladdr,
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
(struct sockaddr_in *)hisctladdr,
(struct sockaddr_in *)myctladdr, &msg_data);
if(ret) {
Curl_failf(data, "Error reading reply from server: %s",
Curl_failf(data, "Error reading reply from server: %s",
krb_get_err_text(ret));
return AUTH_ERROR;
}
@ -317,7 +324,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
save = Curl_set_command_prot(conn, prot_private);
result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->data->state.user);
result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->user);
if(result)
return result;
@ -328,7 +335,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
if(conn->data->state.buffer[0] != '3'){
Curl_set_command_prot(conn, save);
return;
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
p = strstr(conn->data->state.buffer, "T=");
@ -339,7 +346,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
}
p += 2;
tmp = Curl_base64_decode(p, &tkt.dat);
tmp = Curl_base64_decode(p, (char *)tkt.dat);
if(tmp < 0) {
Curl_failf(conn->data, "Failed to decode base64 in reply.\n");
Curl_set_command_prot(conn, save);
@ -347,7 +354,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
}
tkt.length = tmp;
tktcopy.length = tkt.length;
p = strstr(conn->data->state.buffer, "P=");
if(!p) {
Curl_failf(conn->data, "Bad reply from server");
@ -358,26 +365,26 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
*p = 0;
des_string_to_key (conn->data->state.passwd, &key);
des_string_to_key (conn->passwd, &key);
des_key_sched(&key, schedule);
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
if (strcmp ((char*)tktcopy.dat + 8,
KRB_TICKET_GRANTING_TICKET) != 0) {
afs_string_to_key (passwd,
krb_realmofhost(conn->hostname),
&key);
des_key_sched (&key, schedule);
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
afs_string_to_key(passwd,
krb_realmofhost(conn->host.name),
&key);
des_key_sched(&key, schedule);
des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
}
memset(key, 0, sizeof(key));
memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd));
if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
if(Curl_base64_encode((char *)tktcopy.dat, tktcopy.length, &p) < 1) {
failf(conn->data, "Out of memory base64-encoding.");
Curl_set_command_prot(conn, save);
return CURLE_OUT_OF_MEMORY;
@ -397,13 +404,5 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
return CURLE_OK;
}
#endif /* KRB4 */
#endif /* HAVE_KRB4 */
#endif /* CURL_DISABLE_FTP */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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

View File

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

View File

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -25,6 +25,5 @@
***************************************************************************/
#ifndef CURL_DISABLE_LDAP
CURLcode Curl_ldap(struct connectdata *conn);
CURLcode Curl_ldap_done(struct connectdata *conn);
#endif
#endif /* __LDAP_H */

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -27,12 +27,12 @@
#include <stdlib.h>
#include "llist.h"
#include "memory.h"
#ifdef MALLOCDEBUG
/* this must be the last include file */
#include "memdebug.h"
#endif
void
void
Curl_llist_init(curl_llist *l, curl_llist_dtor dtor)
{
l->size = 0;
@ -55,24 +55,31 @@ Curl_llist_alloc(curl_llist_dtor dtor)
return list;
}
/*
* Curl_llist_insert_next() returns 1 on success and 0 on failure.
*/
int
Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
{
curl_llist_element *ne;
curl_llist_element *ne =
(curl_llist_element *) malloc(sizeof(curl_llist_element));
if(!ne)
return 0;
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
ne->ptr = (void *) p;
if (list->size == 0) {
list->head = ne;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = ne;
} else {
}
else {
ne->next = e->next;
ne->prev = e;
if (e->next) {
e->next->prev = ne;
} else {
}
else {
list->tail = ne;
}
e->next = ne;
@ -83,34 +90,7 @@ Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p)
return 1;
}
int
Curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p)
{
curl_llist_element *ne;
ne = (curl_llist_element *) malloc(sizeof(curl_llist_element));
ne->ptr = (void *) p;
if (list->size == 0) {
list->head = ne;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = ne;
} else {
ne->next = e;
ne->prev = e->prev;
if (e->prev)
e->prev->next = ne;
else
list->head = ne;
e->prev = ne;
}
++list->size;
return 1;
}
int
int
Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
{
if (e == NULL || list->size == 0)
@ -138,31 +118,13 @@ Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user)
return 1;
}
int
Curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user)
{
return Curl_llist_remove(list, e->next, user);
}
int
Curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user)
{
return Curl_llist_remove(list, e->prev, user);
}
size_t
Curl_llist_count(curl_llist *list)
{
return list->size;
}
void
void
Curl_llist_destroy(curl_llist *list, void *user)
{
while (list->size > 0) {
Curl_llist_remove(list, CURL_LLIST_TAIL(list), user);
}
if(list) {
while (list->size > 0)
Curl_llist_remove(list, list->tail, user);
free(list);
list = NULL;
free(list);
}
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -53,12 +53,4 @@ int Curl_llist_remove_next(curl_llist *, curl_llist_element *, void *);
size_t Curl_llist_count(curl_llist *);
void Curl_llist_destroy(curl_llist *, void *);
#define CURL_LLIST_HEAD(__l) ((__l)->head)
#define CURL_LLIST_TAIL(__l) ((__l)->tail)
#define CURL_LLIST_NEXT(__e) ((__e)->next)
#define CURL_LLIST_PREV(__e) ((__e)->prev)
#define CURL_LLIST_VALP(__e) ((__e)->ptr)
#define CURL_LLIST_IS_TAIL(__e) ((__e)->next ? 0 : 1)
#define CURL_LLIST_IS_HEAD(__e) ((__e)->prev ? 0 : 1)
#endif

348
Source/CTest/Curl/md5.c Normal file
View File

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

29
Source/CTest/Curl/md5.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __MD5_H
#define __MD5_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
void Curl_md5it(unsigned char *output,
unsigned char *input);
#endif

View File

@ -1,17 +1,17 @@
#ifdef MALLOCDEBUG
#ifdef CURLDEBUG
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -26,13 +26,9 @@
#include <curl/curl.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#else /* some kind of unix */
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#endif
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
@ -45,10 +41,12 @@
#include <unistd.h>
#endif
/* DONT include memdebug.h here! */
#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
#include "memory.h"
#include "memdebug.h"
struct memdebug {
int size;
size_t size;
double mem[1];
/* I'm hoping this is the thing with the strictest alignment
* requirements. That also means we waste some space :-( */
@ -62,7 +60,10 @@ struct memdebug {
* Don't use these with multithreaded test programs!
*/
FILE *logfile;
#define logfile curl_debuglogfile
FILE *curl_debuglogfile;
static bool memlimit; /* enable memory limit */
static long memsize; /* set number of mallocs allowed */
/* this sets the log file name */
void curl_memdebug(const char *logname)
@ -73,16 +74,54 @@ void curl_memdebug(const char *logname)
logfile = stderr;
}
/* This function sets the number of malloc() calls that should return
successfully! */
void curl_memlimit(long limit)
{
memlimit = TRUE;
memsize = limit;
}
/* returns TRUE if this isn't allowed! */
static bool countcheck(const char *func, int line, const char *source)
{
/* if source is NULL, then the call is made internally and this check
should not be made */
if(memlimit && source) {
if(!memsize) {
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
if(source)
fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
source, line, func);
return TRUE; /* RETURN ERROR! */
}
else
memsize--; /* countdown */
/* log the countdown */
if(logfile && source)
fprintf(logfile, "LIMIT %s:%d %ld ALLOCS left\n",
source, line, memsize);
}
return FALSE; /* allow this */
}
void *curl_domalloc(size_t wantedsize, int line, const char *source)
{
struct memdebug *mem;
size_t size;
if(countcheck("malloc", line, source))
return NULL;
/* alloc at least 64 bytes */
size = sizeof(struct memdebug)+wantedsize;
mem=(struct memdebug *)(malloc)(size);
mem=(struct memdebug *)(Curl_cmalloc)(size);
if(mem) {
/* fill memory with junk */
memset(mem->mem, 0xA5, wantedsize);
@ -90,46 +129,78 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
}
if(logfile && source)
fprintf(logfile, "MEM %s:%d malloc(%d) = %p\n",
source, line, wantedsize, mem->mem);
return mem->mem;
fprintf(logfile, "MEM %s:%d malloc(%zd) = %p\n",
source, line, wantedsize, mem ? mem->mem : 0);
return (mem ? mem->mem : NULL);
}
void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
int line, const char *source)
{
struct memdebug *mem;
size_t size, user_size;
if(countcheck("calloc", line, source))
return NULL;
/* alloc at least 64 bytes */
user_size = wanted_size * wanted_elements;
size = sizeof(struct memdebug) + user_size;
mem = (struct memdebug *)(Curl_cmalloc)(size);
if(mem) {
/* fill memory with zeroes */
memset(mem->mem, 0, user_size);
mem->size = user_size;
}
if(logfile && source)
fprintf(logfile, "MEM %s:%d calloc(%u,%u) = %p\n",
source, line, wanted_elements, wanted_size, mem ? mem->mem : 0);
return (mem ? mem->mem : NULL);
}
char *curl_dostrdup(const char *str, int line, const char *source)
{
char *mem;
size_t len;
if(NULL ==str) {
fprintf(stderr, "ILLEGAL strdup() on NULL at %s:%d\n",
source, line);
exit(2);
}
curlassert(str != NULL);
if(countcheck("strdup", line, source))
return NULL;
len=strlen(str)+1;
mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
if (mem)
memcpy(mem, str, len);
if(logfile)
fprintf(logfile, "MEM %s:%d strdup(%p) (%d) = %p\n",
fprintf(logfile, "MEM %s:%d strdup(%p) (%zd) = %p\n",
source, line, str, len, mem);
return mem;
}
/* We provide a realloc() that accepts a NULL as pointer, which then
performs a malloc(). In order to work with ares. */
void *curl_dorealloc(void *ptr, size_t wantedsize,
int line, const char *source)
{
struct memdebug *mem;
struct memdebug *mem=NULL;
size_t size = sizeof(struct memdebug)+wantedsize;
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
if(countcheck("realloc", line, source))
return NULL;
mem=(struct memdebug *)(realloc)(mem, size);
if(ptr)
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
mem=(struct memdebug *)(Curl_crealloc)(mem, size);
if(logfile)
fprintf(logfile, "MEM %s:%d realloc(%p, %d) = %p\n",
fprintf(logfile, "MEM %s:%d realloc(0x%x, %zd) = %p\n",
source, line, ptr, wantedsize, mem?mem->mem:NULL);
if(mem) {
@ -144,35 +215,35 @@ void curl_dofree(void *ptr, int line, const char *source)
{
struct memdebug *mem;
if(NULL == ptr) {
fprintf(stderr, "ILLEGAL free() on NULL at %s:%d\n",
source, line);
exit(2);
}
curlassert(ptr != NULL);
mem = (struct memdebug *)((char *)ptr - offsetof(struct memdebug, mem));
/* destroy */
memset(mem->mem, 0x13, mem->size);
/* free for real */
(free)(mem);
(Curl_cfree)(mem);
if(logfile)
fprintf(logfile, "MEM %s:%d free(%p)\n", source, line, ptr);
}
int curl_socket(int domain, int type, int protocol, int line, char *source)
int curl_socket(int domain, int type, int protocol, int line,
const char *source)
{
int sockfd=(socket)(domain, type, protocol);
if(logfile)
if(logfile && (sockfd!=-1))
fprintf(logfile, "FD %s:%d socket() = %d\n",
source, line, sockfd);
return sockfd;
}
int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
int curl_accept(int s, void *saddr, void *saddrlen,
int line, const char *source)
{
struct sockaddr *addr = (struct sockaddr *)saddr;
socklen_t *addrlen = (socklen_t *)saddrlen;
int sockfd=(accept)(s, addr, addrlen);
if(logfile)
fprintf(logfile, "FD %s:%d accept() = %d\n",
@ -181,7 +252,7 @@ int curl_accept(int s, struct sockaddr *addr, socklen_t *addrlen,
}
/* this is our own defined way to close sockets on *ALL* platforms */
int curl_sclose(int sockfd, int line, char *source)
int curl_sclose(int sockfd, int line, const char *source)
{
int res=sclose(sockfd);
if(logfile)
@ -195,8 +266,8 @@ FILE *curl_fopen(const char *file, const char *mode,
{
FILE *res=(fopen)(file, mode);
if(logfile)
fprintf(logfile, "FILE %s:%d fopen(\"%s\") = %p\n",
source, line, file, res);
fprintf(logfile, "FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
source, line, file, mode, res);
return res;
}
@ -204,11 +275,7 @@ int curl_fclose(FILE *file, int line, const char *source)
{
int res;
if(NULL == file) {
fprintf(stderr, "ILLEGAL flose() on NULL at %s:%d\n",
source, line);
exit(2);
}
curlassert(file != NULL);
res=(fclose)(file);
if(logfile)
@ -218,14 +285,9 @@ int curl_fclose(FILE *file, int line, const char *source)
}
#else
#ifdef VMS
int VOID_VAR_MEMDEBUG;
#endif
#endif /* MALLOCDEBUG */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
int VOID_VAR_MEMDEBUG;
#else
/* we provide a fake do-nothing function here to avoid compiler warnings */
void curl_memdebug(void) {}
#endif /* VMS */
#endif /* CURLDEBUG */

View File

@ -1,4 +1,6 @@
#ifdef MALLOCDEBUG
#ifdef CURLDEBUG
#ifndef _CURL_MEDEBUG_H
#define _CURL_MEDEBUG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@ -6,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -22,6 +24,11 @@
* $Id$
***************************************************************************/
/*
* CAUTION: this header is designed to work when included by the app-side
* as well as the library. Do not mix with library internals!
*/
#include "setup.h"
#ifdef HAVE_SYS_TYPES_H
@ -36,19 +43,23 @@
#include <memory.h>
#endif
#define logfile curl_debuglogfile
extern FILE *logfile;
/* memory functions */
void *curl_domalloc(size_t size, int line, const char *source);
void *curl_docalloc(size_t elements, size_t size, int line, const char *source);
void *curl_dorealloc(void *ptr, size_t size, int line, const char *source);
void curl_dofree(void *ptr, int line, const char *source);
char *curl_dostrdup(const char *str, int line, const char *source);
void curl_memdebug(const char *logname);
void curl_memlimit(long limit);
/* file descriptor manipulators */
int curl_socket(int domain, int type, int protocol, int, const char *);
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, struct sockaddr *addr, socklen_t *addrlen,
int curl_accept(int s, void *addr, void *addrlen,
int line, const char *source);
/* FILE functions */
@ -56,29 +67,42 @@ FILE *curl_fopen(const char *file, const char *mode, int line,
const char *source);
int curl_fclose(FILE *file, int line, const char *source);
#ifndef MEMDEBUG_NODEFINES
/* Set this symbol on the command-line, recompile all lib-sources */
#undef strdup
#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
#define malloc(size) curl_domalloc(size, __LINE__, __FILE__)
#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__)
#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
#define socket(domain,type,protocol)\
curl_socket(domain,type,protocol,__LINE__,__FILE__)
#undef accept /* for those with accept as a macro */
#define accept(sock,addr,len)\
curl_accept(sock,addr,len,__LINE__,__FILE__)
#define getaddrinfo(host,serv,hint,res) \
curl_getaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
curl_dogetaddrinfo(host,serv,hint,res,__LINE__,__FILE__)
#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
curl_dogetnameinfo(sa,salen,host,hostlen,serv,servlen,flags, __LINE__, \
__FILE__)
#define freeaddrinfo(data) \
curl_freeaddrinfo(data,__LINE__,__FILE__)
curl_dofreeaddrinfo(data,__LINE__,__FILE__)
/* sclose is probably already defined, redefine it! */
#undef sclose
#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
/* ares-adjusted define: */
#undef closesocket
#define closesocket(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
#undef fopen
#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__)
#define fclose(file) curl_fclose(file,__LINE__,__FILE__)
#endif
#endif /* MEMDEBUG_NODEFINES */
#endif /* _CURL_MEDEBUG_H */
#endif /* CURLDEBUG */

View File

@ -0,0 +1,50 @@
#ifndef _CURL_MEMORY_H
#define _CURL_MEMORY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include <curl/curl.h> /* for the typedefs */
extern curl_malloc_callback Curl_cmalloc;
extern curl_free_callback Curl_cfree;
extern curl_realloc_callback Curl_crealloc;
extern curl_strdup_callback Curl_cstrdup;
extern curl_calloc_callback Curl_ccalloc;
#ifndef CURLDEBUG
/* Only do this define-mania if we're not using the memdebug system, as that
has preference on this magic. */
#undef strdup
#define strdup(ptr) Curl_cstrdup(ptr)
#undef malloc
#define malloc(size) Curl_cmalloc(size)
#undef calloc
#define calloc(nbelem,size) Curl_ccalloc(nbelem, size)
#undef realloc
#define realloc(ptr,size) Curl_crealloc(ptr, size)
#undef free
#define free(ptr) Curl_cfree(ptr)
#endif
#endif /* _CURL_MEMORY_H */

View File

@ -38,20 +38,27 @@
#include <ctype.h>
#include <string.h>
#ifndef SIZEOF_LONG_LONG
/* prevents warnings on picky compilers */
#define SIZEOF_LONG_LONG 0
#endif
#include <curl/mprintf.h>
#ifndef SIZEOF_LONG_DOUBLE
#define SIZEOF_LONG_DOUBLE 0
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#ifndef SIZEOF_SIZE_T
/* default to 4 bytes for size_t unless defined in the config.h */
#define SIZEOF_SIZE_T 4
#endif
#ifdef DPRINTF_DEBUG
#define HAVE_LONGLONG
#define LONG_LONG long long
#define ENABLE_64BIT
#endif
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
#define MAX_PARAMETERS 128 /* lame static limit */
@ -75,7 +82,13 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
/* Upper-case digits. */
static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define OUTCHAR(x) done+=(stream(x, (FILE *)data)==-1?0:1)
#define OUTCHAR(x) \
do{ \
if(stream((unsigned char)(x), (FILE *)data) != -1) \
done++; \
else \
return done; /* return immediately on failure */ \
} while(0)
/* Data type to read from the arglist */
typedef enum {
@ -119,19 +132,16 @@ enum {
typedef struct {
FormatType type;
int flags;
int width; /* width OR width parameter number */
int precision; /* precision OR precision parameter number */
long width; /* width OR width parameter number */
long precision; /* precision OR precision parameter number */
union {
char *str;
void *ptr;
long num;
#if SIZEOF_LONG_LONG /* if this is non-zero */
long long lnum;
#ifdef ENABLE_64BIT
LONG_LONG lnum;
#endif
double dnum;
#if SIZEOF_LONG_DOUBLE
long double ldnum;
#endif
} data;
} va_stack_t;
@ -145,11 +155,13 @@ struct asprintf {
char *buffer; /* allocated buffer */
size_t len; /* length of string */
size_t alloc; /* length of alloc */
bool fail; /* TRUE if an alloc has failed and thus the output is not
the complete data */
};
int curl_msprintf(char *buffer, const char *format, ...);
static int dprintf_DollarString(char *input, char **end)
static long dprintf_DollarString(char *input, char **end)
{
int number=0;
while(isdigit((int)*input)) {
@ -170,7 +182,8 @@ static BOOL dprintf_IsQualifierNoDollar(char c)
case '-': case '+': case ' ': case '#': case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'h': case 'l': case 'L': case 'Z': case 'q':
case 'h': case 'l': case 'L': case 'z': case 'q':
case '*': case 'O':
return TRUE;
default:
return FALSE;
@ -211,7 +224,7 @@ int dprintf_Pass1Report(va_stack_t *vto, int max)
break;
case FORMAT_LONGDOUBLE:
type = "long double";
break;
break;
}
@ -277,16 +290,17 @@ int dprintf_Pass1Report(va_stack_t *vto, int max)
*
******************************************************************/
static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list arglist)
static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos,
va_list arglist)
{
char *fmt = format;
int param_num = 0;
int this_param;
int width;
int precision;
long this_param;
long width;
long precision;
int flags;
int max_param=0;
int i;
long max_param=0;
long i;
while (*fmt) {
if (*fmt++ == '%') {
@ -300,7 +314,7 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
/* Handle the positional case (N$) */
param_num++;
this_param = dprintf_DollarString(fmt, &fmt);
if (0 == this_param)
/* we got no positional, get the next counter */
@ -373,11 +387,21 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
case 'q':
flags |= FLAGS_LONGLONG;
break;
case 'Z':
if (sizeof(size_t) > sizeof(unsigned long int))
flags |= FLAGS_LONGLONG;
if (sizeof(size_t) > sizeof(unsigned int))
flags |= FLAGS_LONG;
case 'z':
/* the code below generates a warning if -Wunreachable-code is
used */
#if SIZEOF_SIZE_T>4
flags |= FLAGS_LONGLONG;
#else
flags |= FLAGS_LONG;
#endif
break;
case 'O':
#if SIZEOF_CURL_OFF_T > 4
flags |= FLAGS_LONGLONG;
#else
flags |= FLAGS_LONG;
#endif
break;
case '0':
if (!(flags & FLAGS_LEFT))
@ -391,7 +415,7 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
case '*': /* Special case */
flags |= FLAGS_WIDTHPARAM;
param_num++;
i = dprintf_DollarString(fmt, &fmt);
if(i)
width = i;
@ -444,18 +468,26 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
case 'c':
vto[i].type = FORMAT_INT;
flags |= FLAGS_CHAR;
break;
break;
case 'f':
vto[i].type = FORMAT_DOUBLE;
break;
case 'e': case 'E':
case 'e':
vto[i].type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATE| (('E' == *fmt)?FLAGS_UPPER:0);
flags |= FLAGS_FLOATE;
break;
case 'g': case 'G':
case 'E':
vto[i].type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATG| (('G' == *fmt)?FLAGS_UPPER:0);
break;
flags |= FLAGS_FLOATE|FLAGS_UPPER;
break;
case 'g':
vto[i].type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATG;
break;
case 'G':
vto[i].type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATG|FLAGS_UPPER;
break;
default:
vto[i].type = FORMAT_UNKNOWN;
break;
@ -464,7 +496,7 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
vto[i].flags = flags;
vto[i].width = width;
vto[i].precision = precision;
if (flags & FLAGS_WIDTHPARAM) {
/* we have the width specified from a parameter, so we make that
parameter's info setup properly */
@ -473,7 +505,7 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
vto[i].type = FORMAT_WIDTH;
vto[i].flags = FLAGS_NEW;
vto[i].precision = vto[i].width = 0; /* can't use width or precision
of width! */
of width! */
}
if (flags & FLAGS_PRECPARAM) {
/* we have the precision specified from a parameter, so we make that
@ -508,17 +540,17 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
case FORMAT_STRING:
vto[i].data.str = va_arg(arglist, char *);
break;
case FORMAT_INTPTR:
case FORMAT_UNKNOWN:
case FORMAT_PTR:
vto[i].data.ptr = va_arg(arglist, void *);
break;
case FORMAT_INT:
#if SIZEOF_LONG_LONG
#ifdef ENABLE_64BIT
if(vto[i].flags & FLAGS_LONGLONG)
vto[i].data.lnum = va_arg(arglist, long long);
vto[i].data.lnum = va_arg(arglist, LONG_LONG);
else
#endif
if(vto[i].flags & FLAGS_LONG)
@ -526,23 +558,18 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
else
vto[i].data.num = va_arg(arglist, int);
break;
case FORMAT_DOUBLE:
#if SIZEOF_LONG_DOUBLE
if(vto[i].flags & FLAGS_LONG)
vto[i].data.ldnum = va_arg(arglist, long double);
else
#endif
vto[i].data.dnum = va_arg(arglist, double);
vto[i].data.dnum = va_arg(arglist, double);
break;
case FORMAT_WIDTH:
/* Argument has been read. Silently convert it into an integer
* for later use
*/
vto[i].type = FORMAT_INT;
break;
default:
break;
}
@ -553,12 +580,12 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
}
static int dprintf_formatf(
void *data, /* untouched by format(), just sent to the
stream() function in the first argument */
int (*stream)(int, FILE *), /* function pointer called for each
output character */
const char *format, /* %-formatted string */
va_list ap_save) /* list of parameters */
void *data, /* untouched by format(), just sent to the stream() function in
the second argument */
/* function pointer called for each output character */
int (*stream)(int, FILE *),
const char *format, /* %-formatted string */
va_list ap_save) /* list of parameters */
{
/* Base-36 digits for numbers. */
const char *digits = lower_digits;
@ -567,7 +594,7 @@ static int dprintf_formatf(
char *f;
/* Number of characters written. */
register size_t done = 0;
int done = 0;
long param; /* current parameter to read */
long param_num=0; /* parameter counter */
@ -585,31 +612,32 @@ static int dprintf_formatf(
end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
created for us */
f = (char *)format;
while (*f != '\0') {
/* Format spec modifiers. */
char alt;
/* Width of a field. */
register long width;
long width;
/* Precision of a field. */
long prec;
/* Decimal integer is negative. */
char is_neg;
/* Base of a number to be written. */
long base;
/* Integral values to be written. */
#if SIZEOF_LONG_LONG
unsigned long long num;
#ifdef ENABLE_64BIT
unsigned LONG_LONG num;
#else
unsigned long num;
#endif
long signed_num;
if (*f != '%') {
/* This isn't a format spec, so write everything out until the next one
OR end of string is reached. */
@ -618,9 +646,9 @@ static int dprintf_formatf(
} while(*++f && ('%' != *f));
continue;
}
++f;
/* Check for "%%". Note that although the ANSI standard lists
'%' as a conversion specifier, it says "The complete format
specification shall be `%%'," so we can avoid all the width
@ -639,7 +667,7 @@ static int dprintf_formatf(
param = param_num;
else
--param;
param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
third %s will pick the 3rd argument */
@ -659,8 +687,8 @@ static int dprintf_formatf(
else
prec = -1;
alt = (char)(p->flags & FLAGS_ALT);
alt = (p->flags & FLAGS_ALT)?TRUE:FALSE;
switch (p->type) {
case FORMAT_INT:
num = p->data.num;
@ -696,9 +724,9 @@ static int dprintf_formatf(
/* Decimal integer. */
base = 10;
#if SIZEOF_LONG_LONG
#ifdef ENABLE_64BIT
if(p->flags & FLAGS_LONGLONG) {
/* long long */
/* long long */
is_neg = p->data.lnum < 0;
num = is_neg ? (- p->data.lnum) : p->data.lnum;
}
@ -706,63 +734,62 @@ static int dprintf_formatf(
#endif
{
signed_num = (long) num;
is_neg = (char)(signed_num < 0);
is_neg = signed_num < 0;
num = is_neg ? (- signed_num) : signed_num;
}
goto number;
unsigned_number:;
unsigned_number:
/* Unsigned number of base BASE. */
is_neg = 0;
number:;
number:
/* Number of base BASE. */
{
char *workend = &work[sizeof(work) - 1];
register char *w;
char *w;
/* Supply a default precision if none was given. */
if (prec == -1)
prec = 1;
/* Put the number in WORK. */
w = workend;
while (num > 0) {
*w-- = digits[num % base];
num /= base;
}
width -= (long)(workend - w);
prec -= (long)(workend - w);
width -= workend - w;
prec -= workend - w;
if (alt && base == 8 && prec <= 0) {
*w-- = '0';
--width;
}
if (prec > 0) {
width -= prec;
while (prec-- > 0)
*w-- = '0';
}
if (alt && base == 16)
width -= 2;
if (is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
--width;
if (!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
while (width-- > 0)
OUTCHAR(' ');
if (is_neg)
OUTCHAR('-');
else if (p->flags & FLAGS_SHOWSIGN)
OUTCHAR('+');
else if (p->flags & FLAGS_SPACE)
OUTCHAR(' ');
if (alt && base == 16) {
OUTCHAR('0');
if(p->flags & FLAGS_UPPER)
@ -774,25 +801,25 @@ static int dprintf_formatf(
if (!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
while (width-- > 0)
OUTCHAR('0');
/* Write the number. */
while (++w <= workend) {
OUTCHAR(*w);
}
if (p->flags & FLAGS_LEFT)
while (width-- > 0)
OUTCHAR(' ');
}
break;
case FORMAT_STRING:
/* String. */
{
static char null[] = "(nil)";
char *str;
size_t len;
str = (char *) p->data.str;
if ( str == NULL) {
/* Write null[] if there's space. */
@ -809,10 +836,10 @@ static int dprintf_formatf(
}
else
len = strlen(str);
if (prec != -1 && (size_t) prec < len)
len = prec;
width -= (long)len;
width -= len;
if (p->flags & FLAGS_ALT)
OUTCHAR('"');
@ -820,7 +847,7 @@ static int dprintf_formatf(
if (!(p->flags&FLAGS_LEFT))
while (width-- > 0)
OUTCHAR(' ');
while (len-- > 0)
OUTCHAR(*str++);
if (p->flags&FLAGS_LEFT)
@ -831,7 +858,7 @@ static int dprintf_formatf(
OUTCHAR('"');
}
break;
case FORMAT_PTR:
/* Generic pointer. */
{
@ -849,8 +876,8 @@ static int dprintf_formatf(
else {
/* Write "(nil)" for a nil pointer. */
static char strnil[] = "(nil)";
register char *point;
char *point;
width -= sizeof(strnil) - 1;
if (p->flags & FLAGS_LEFT)
while (width-- > 0)
@ -868,7 +895,9 @@ static int dprintf_formatf(
{
char formatbuf[32]="%";
char *fptr;
size_t left = sizeof(formatbuf)-strlen(formatbuf);
int len;
width = -1;
if (p->flags & FLAGS_WIDTH)
width = p->width;
@ -894,31 +923,31 @@ static int dprintf_formatf(
if(width >= 0) {
/* RECURSIVE USAGE */
fptr += curl_msprintf(fptr, "%d", width);
len = curl_msnprintf(fptr, left, "%ld", width);
fptr += len;
left -= len;
}
if(prec >= 0) {
/* RECURSIVE USAGE */
fptr += curl_msprintf(fptr, ".%d", prec);
len = curl_msnprintf(fptr, left, ".%ld", prec);
fptr += len;
left -= len;
}
if (p->flags & FLAGS_LONG)
strcat(fptr, "l");
*fptr++ = 'l';
if (p->flags & FLAGS_FLOATE)
strcat(fptr, p->flags&FLAGS_UPPER?"E":"e");
*fptr++ = p->flags&FLAGS_UPPER ? 'E':'e';
else if (p->flags & FLAGS_FLOATG)
strcat(fptr, (p->flags & FLAGS_UPPER) ? "G" : "g");
*fptr++ = p->flags & FLAGS_UPPER ? 'G' : 'g';
else
strcat(fptr, "f");
*fptr++ = 'f';
*fptr = 0; /* and a final zero termination */
/* NOTE NOTE NOTE!! Not all sprintf() implementations returns number
of output characters */
#if SIZEOF_LONG_DOUBLE
if (p->flags & FLAGS_LONG)
/* This is for support of the 'long double' type */
(sprintf)(work, formatbuf, p->data.ldnum);
else
#endif
(sprintf)(work, formatbuf, p->data.dnum);
(sprintf)(work, formatbuf, p->data.dnum);
for(fptr=work; *fptr; fptr++)
OUTCHAR(*fptr);
@ -927,17 +956,17 @@ static int dprintf_formatf(
case FORMAT_INTPTR:
/* Answer the count of characters written. */
#if SIZEOF_LONG_LONG
#ifdef ENABLE_64BIT
if (p->flags & FLAGS_LONGLONG)
*(long long int *) p->data.ptr = done;
*(LONG_LONG *) p->data.ptr = (LONG_LONG)done;
else
#endif
if (p->flags & FLAGS_LONG)
*(long int *) p->data.ptr = (long int)done;
*(long *) p->data.ptr = (long)done;
else if (!(p->flags & FLAGS_SHORT))
*(int *) p->data.ptr = (int)done;
else
*(short int *) p->data.ptr = (short int)done;
*(short *) p->data.ptr = (short)done;
break;
default:
@ -946,68 +975,69 @@ static int dprintf_formatf(
f = *end++; /* goto end of %-code */
}
return (int)done;
return done;
}
/* fputc() look-alike */
static int addbyter(int output, FILE *data)
{
struct nsprintf *infop=(struct nsprintf *)data;
unsigned char outc = (unsigned char)output;
if(infop->length < infop->max) {
/* only do this if we haven't reached max length yet */
infop->buffer[0] = (char)output; /* store */
infop->buffer[0] = outc; /* store */
infop->buffer++; /* increase pointer */
infop->length++; /* we are now one byte larger */
return output; /* fputc() returns like this on success */
return outc; /* fputc() returns like this on success */
}
return -1;
}
int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
va_list ap_save)
{
int retcode;
struct nsprintf info;
info.buffer = buffer;
info.length = 0;
info.max = maxlength;
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
if(info.max) {
/* we terminate this with a zero byte */
if(info.max == info.length)
/* we're at maximum, scrap the last letter */
info.buffer[-1] = 0;
else
info.buffer[0] = 0;
}
return retcode;
}
int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
{
int retcode;
va_list ap_save; /* argument pointer */
int retcode;
struct nsprintf info;
info.buffer = buffer;
info.length = 0;
info.max = maxlength;
va_start(ap_save, format);
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
va_end(ap_save);
info.buffer[0] = 0; /* we terminate this with a zero byte */
/* we could even return things like */
return retcode;
}
int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, va_list ap_save)
{
int retcode;
struct nsprintf info;
info.buffer = buffer;
info.length = 0;
info.max = maxlength;
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
info.buffer[0] = 0; /* we terminate this with a zero byte */
return retcode;
}
/* fputc() look-alike */
static int alloc_addbyter(int output, FILE *data)
{
struct asprintf *infop=(struct asprintf *)data;
unsigned char outc = (unsigned char)output;
if(!infop->buffer) {
infop->buffer=(char *)malloc(32);
if(!infop->buffer)
if(!infop->buffer) {
infop->fail = TRUE;
return -1; /* fail */
}
infop->alloc = 32;
infop->len =0;
}
@ -1017,17 +1047,18 @@ static int alloc_addbyter(int output, FILE *data)
newptr = (char *)realloc(infop->buffer, infop->alloc*2);
if(!newptr) {
infop->fail = TRUE;
return -1;
}
infop->buffer = newptr;
infop->alloc *= 2;
}
infop->buffer[ infop->len ] = (char)output;
infop->buffer[ infop->len ] = outc;
infop->len++;
return output; /* fputc() returns like this on success */
return outc; /* fputc() returns like this on success */
}
char *curl_maprintf(const char *format, ...)
@ -1039,11 +1070,12 @@ char *curl_maprintf(const char *format, ...)
info.buffer = NULL;
info.len = 0;
info.alloc = 0;
info.fail = FALSE;
va_start(ap_save, format);
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
va_end(ap_save);
if(-1 == retcode) {
if((-1 == retcode) || info.fail) {
if(info.alloc)
free(info.buffer);
return NULL;
@ -1064,9 +1096,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
info.buffer = NULL;
info.len = 0;
info.alloc = 0;
info.fail = FALSE;
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
if(-1 == retcode) {
if((-1 == retcode) || info.fail) {
if(info.alloc)
free(info.buffer);
return NULL;
@ -1083,9 +1116,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
static int storebuffer(int output, FILE *data)
{
char **buffer = (char **)data;
**buffer = (char)output;
unsigned char outc = (unsigned char)output;
**buffer = outc;
(*buffer)++;
return output; /* act like fputc() ! */
return outc; /* act like fputc() ! */
}
int curl_msprintf(char *buffer, const char *format, ...)
@ -1146,14 +1180,16 @@ int main()
{
char buffer[129];
char *ptr;
#if SIZEOF_LONG_LONG>0
long long hullo;
dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65);
#ifdef ENABLE_64BIT
long long one=99;
long long two=100;
long long test = 0x1000000000LL;
curl_mprintf("%lld %lld %lld\n", one, two, test);
#endif
mprintf("%3d %5d\n", 10, 1998);
ptr=maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a hit in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001);
curl_mprintf("%3d %5d\n", 10, 1998);
ptr=curl_maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a hit in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001);
puts(ptr);
@ -1162,15 +1198,15 @@ int main()
free(ptr);
#if 1
mprintf(buffer, "%s %s %d", "daniel", "stenberg", 19988);
curl_mprintf(buffer, "%s %s %d", "daniel", "stenberg", 19988);
puts(buffer);
mfprintf(stderr, "%s %#08x\n", "dummy", 65);
curl_mfprintf(stderr, "%s %#08x\n", "dummy", 65);
printf("%s %#08x\n", "dummy", 65);
{
double tryout = 3.14156592;
mprintf(buffer, "%.2g %G %f %e %E", tryout, tryout, tryout, tryout, tryout);
curl_mprintf(buffer, "%.2g %G %f %e %E", tryout, tryout, tryout, tryout, tryout);
puts(buffer);
printf("%.2g %G %f %e %E\n", tryout, tryout, tryout, tryout, tryout);
}
@ -1180,11 +1216,3 @@ int main()
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -24,20 +24,28 @@
#include "setup.h"
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "transfer.h"
#include "url.h"
#include "connect.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "progress.h"
#include "memory.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
struct Curl_message {
/* the 'CURLMsg' is the part that is visible to the external user */
@ -47,7 +55,8 @@ struct Curl_message {
typedef enum {
CURLM_STATE_INIT,
CURLM_STATE_CONNECT, /* connect has been sent off */
CURLM_STATE_CONNECT, /* resolve/connect has been sent off */
CURLM_STATE_WAITRESOLVE, /* we're awaiting the resolve to finalize */
CURLM_STATE_WAITCONNECT, /* we're awaiting the connect to finalize */
CURLM_STATE_DO, /* send off the request (part 1) */
CURLM_STATE_DO_MORE, /* send off the request (part 2) */
@ -62,7 +71,7 @@ struct Curl_one_easy {
/* first, two fields for the linked list of these */
struct Curl_one_easy *next;
struct Curl_one_easy *prev;
struct SessionHandle *easy_handle; /* the easy handle for this unit */
struct connectdata *easy_conn; /* the "unit's" connection */
@ -90,7 +99,7 @@ struct Curl_multi {
long type;
/* We have a linked list with easy handles */
struct Curl_one_easy easy;
struct Curl_one_easy easy;
/* This is the amount of entries in the linked list above. */
int num_easy;
@ -111,7 +120,15 @@ CURLM *curl_multi_init(void)
memset(multi, 0, sizeof(struct Curl_multi));
multi->type = CURL_MULTI_HANDLE;
}
else
return NULL;
multi->hostcache = Curl_mk_dnscache();
if(!multi->hostcache) {
/* failure, free mem and bail out */
free(multi);
multi = NULL;
}
return (CURLM *) multi;
}
@ -124,7 +141,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
/* Verify that we got a somewhat good easy handle too */
if(!GOOD_EASY_HANDLE(easy_handle))
return CURLM_BAD_EASY_HANDLE;
@ -133,18 +150,21 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
easy = (struct Curl_one_easy *)malloc(sizeof(struct Curl_one_easy));
if(!easy)
return CURLM_OUT_OF_MEMORY;
/* clean it all first (just to be sure) */
memset(easy, 0, sizeof(struct Curl_one_easy));
/* set the easy handle */
easy->easy_handle = easy_handle;
easy->state = CURLM_STATE_INIT;
/* for multi interface connections, we share DNS cache automaticly */
easy->easy_handle->hostcache = multi->hostcache;
/* We add this new entry first in the list. We make our 'next' point to the
previous next and our 'prev' point back to the 'first' struct */
easy->next = multi->easy.next;
easy->prev = &multi->easy;
easy->prev = &multi->easy;
/* make 'easy' the first node in the chain */
multi->easy.next = easy;
@ -169,7 +189,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
/* Verify that we got a somewhat good easy handle too */
if(!GOOD_EASY_HANDLE(curl_handle))
return CURLM_BAD_EASY_HANDLE;
@ -177,7 +197,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* scan through the list and remove the 'curl_handle' */
easy = multi->easy.next;
while(easy) {
if((CURL*)(easy->easy_handle) == curl_handle)
if(easy->easy_handle == (struct SessionHandle *)curl_handle)
break;
easy=easy->next;
}
@ -187,14 +207,14 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* clear out the usage of the shared DNS cache */
easy->easy_handle->hostcache = NULL;
/* make the previous node point to our next */
if(easy->prev)
easy->prev->next = easy->next;
/* make our next point to our previous node */
if(easy->next)
easy->next->prev = easy->prev;
/* NOTE NOTE NOTE
We do not touch the easy handle here! */
if (easy->msg)
@ -230,30 +250,37 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
switch(easy->state) {
default:
break;
case CURLM_STATE_WAITRESOLVE:
/* waiting for a resolve to complete */
Curl_fdset(easy->easy_conn, read_fd_set, write_fd_set, &this_max_fd);
if(this_max_fd > *max_fd)
*max_fd = this_max_fd;
break;
case CURLM_STATE_WAITCONNECT:
case CURLM_STATE_DO_MORE:
{
/* when we're waiting for a connect, we wait for the socket to
become writable */
struct connectdata *conn = easy->easy_conn;
int sockfd;
curl_socket_t sockfd;
if(CURLM_STATE_WAITCONNECT == easy->state) {
sockfd = conn->firstsocket;
sockfd = conn->sock[FIRSTSOCKET];
FD_SET(sockfd, write_fd_set);
}
else {
/* When in DO_MORE state, we could be either waiting for us
to connect to a remote site, or we could wait for that site
to connect to us. It makes a difference in the way: if we
connect to the site we wait for the socket to become writable, if
connect to the site we wait for the socket to become writable, if
the site connects to us we wait for it to become readable */
sockfd = conn->secondarysocket;
sockfd = conn->sock[SECONDARYSOCKET];
FD_SET(sockfd, write_fd_set);
}
if(sockfd > *max_fd)
*max_fd = sockfd;
if((int)sockfd > *max_fd)
*max_fd = (int)sockfd;
}
break;
case CURLM_STATE_PERFORM:
@ -284,6 +311,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
CURLMcode result=CURLM_OK;
struct Curl_message *msg = NULL;
bool connected;
bool async;
*running_handles = 0; /* bump this once for every living handle */
@ -292,54 +320,106 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
easy=multi->easy.next;
while(easy) {
#ifdef MALLOCDEBUG
#if 0
fprintf(stderr, "HANDLE %p: State: %x\n",
(char *)easy, easy->state);
#endif
do {
if (CURLM_STATE_WAITCONNECT <= easy->state &&
easy->state <= CURLM_STATE_DO &&
easy->easy_handle->change.url_changed) {
char *gotourl;
Curl_posttransfer(easy->easy_handle);
switch(easy->state) {
case CURLM_STATE_INIT:
/* init this transfer. */
easy->result=Curl_pretransfer(easy->easy_handle);
if(CURLE_OK == easy->result) {
/* after init, go CONNECT */
easy->state = CURLM_STATE_CONNECT;
result = CURLM_CALL_MULTI_PERFORM;
easy->easy_handle->state.used_interface = Curl_if_multi;
}
break;
case CURLM_STATE_CONNECT:
if (Curl_global_host_cache_use(easy->easy_handle)) {
easy->easy_handle->hostcache = Curl_global_host_cache_get();
}
else {
if (multi->hostcache == NULL)
multi->hostcache = Curl_hash_alloc(7, Curl_freednsinfo);
easy->easy_handle->hostcache = multi->hostcache;
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
if(CURLE_OK == easy->result) {
gotourl = strdup(easy->easy_handle->change.url);
if(gotourl) {
easy->easy_handle->change.url_changed = FALSE;
easy->result = Curl_follow(easy->easy_handle, gotourl);
if(CURLE_OK == easy->result)
easy->state = CURLM_STATE_CONNECT;
else
free(gotourl);
}
else {
easy->result = CURLE_OUT_OF_MEMORY;
easy->state = CURLM_STATE_COMPLETED;
break;
}
}
}
/* Connect. We get a connection identifier filled in. */
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
easy->easy_handle->change.url_changed = FALSE;
/* after the connect has been sent off, go WAITCONNECT */
if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_WAITCONNECT;
result = CURLM_CALL_MULTI_PERFORM;
}
break;
switch(easy->state) {
case CURLM_STATE_INIT:
/* init this transfer. */
easy->result=Curl_pretransfer(easy->easy_handle);
case CURLM_STATE_WAITCONNECT:
if(CURLE_OK == easy->result) {
/* after init, go CONNECT */
easy->state = CURLM_STATE_CONNECT;
result = CURLM_CALL_MULTI_PERFORM;
easy->easy_handle->state.used_interface = Curl_if_multi;
}
break;
case CURLM_STATE_CONNECT:
/* Connect. We get a connection identifier filled in. */
Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
&async);
if(CURLE_OK == easy->result) {
if(async)
/* We're now waiting for an asynchronous name lookup */
easy->state = CURLM_STATE_WAITRESOLVE;
else {
/* after the connect has been sent off, go WAITCONNECT */
easy->state = CURLM_STATE_WAITCONNECT;
result = CURLM_CALL_MULTI_PERFORM;
}
}
break;
case CURLM_STATE_WAITRESOLVE:
/* awaiting an asynch name resolve to complete */
{
bool connected;
easy->result = Curl_is_connected(easy->easy_conn,
easy->easy_conn->firstsocket,
struct Curl_dns_entry *dns = NULL;
/* check if we have the name resolved by now */
easy->result = Curl_is_resolved(easy->easy_conn, &dns);
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
easy->result = Curl_async_resolved(easy->easy_conn);
if(CURLE_OK != easy->result)
/* if Curl_async_resolved() returns failure, the connection struct
is already freed and gone */
easy->easy_conn = NULL; /* no more connection */
easy->state = CURLM_STATE_WAITCONNECT;
}
if(CURLE_OK != easy->result) {
/* failure detected */
Curl_disconnect(easy->easy_conn); /* disconnect properly */
easy->easy_conn = NULL; /* no more connection */
break;
}
}
break;
case CURLM_STATE_WAITCONNECT:
/* awaiting a completion of an asynch connect */
easy->result = Curl_is_connected(easy->easy_conn, FIRSTSOCKET,
&connected);
if(connected)
easy->result = Curl_protocol_connect(easy->easy_conn, NULL);
easy->result = Curl_protocol_connect(easy->easy_conn);
if(CURLE_OK != easy->result) {
/* failure detected */
@ -351,127 +431,131 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
if(connected) {
/* after the connect has completed, go DO */
easy->state = CURLM_STATE_DO;
result = CURLM_CALL_MULTI_PERFORM;
result = CURLM_CALL_MULTI_PERFORM;
}
}
break;
break;
case CURLM_STATE_DO:
/* Do the fetch or put request */
easy->result = Curl_do(&easy->easy_conn);
if(CURLE_OK == easy->result) {
case CURLM_STATE_DO:
/* Do the fetch or put request */
easy->result = Curl_do(&easy->easy_conn);
if(CURLE_OK == easy->result) {
/* after do, go PERFORM... or DO_MORE */
if(easy->easy_conn->bits.do_more) {
/* we're supposed to do more, but we need to sit down, relax
and wait a little while first */
easy->state = CURLM_STATE_DO_MORE;
result = CURLM_OK;
}
else {
/* we're done with the DO, now PERFORM */
easy->result = Curl_readwrite_init(easy->easy_conn);
if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_PERFORM;
result = CURLM_CALL_MULTI_PERFORM;
/* after do, go PERFORM... or DO_MORE */
if(easy->easy_conn->bits.do_more) {
/* we're supposed to do more, but we need to sit down, relax
and wait a little while first */
easy->state = CURLM_STATE_DO_MORE;
result = CURLM_OK;
}
else {
/* we're done with the DO, now PERFORM */
easy->result = Curl_readwrite_init(easy->easy_conn);
if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_PERFORM;
result = CURLM_CALL_MULTI_PERFORM;
}
}
}
}
break;
break;
case CURLM_STATE_DO_MORE:
/*
* First, check if we really are ready to do more.
*/
easy->result = Curl_is_connected(easy->easy_conn,
easy->easy_conn->secondarysocket,
&connected);
if(connected) {
case CURLM_STATE_DO_MORE:
/*
* When we are connected, DO MORE and then go PERFORM
* First, check if we really are ready to do more.
*/
easy->result = Curl_do_more(easy->easy_conn);
easy->result = Curl_is_connected(easy->easy_conn, SECONDARYSOCKET,
&connected);
if(connected) {
/*
* When we are connected, DO MORE and then go PERFORM
*/
easy->result = Curl_do_more(easy->easy_conn);
if(CURLE_OK == easy->result)
easy->result = Curl_readwrite_init(easy->easy_conn);
if(CURLE_OK == easy->result)
easy->result = Curl_readwrite_init(easy->easy_conn);
if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_PERFORM;
result = CURLM_CALL_MULTI_PERFORM;
}
}
break;
case CURLM_STATE_PERFORM:
/* read/write data if it is ready to do so */
easy->result = Curl_readwrite(easy->easy_conn, &done);
if(easy->result) {
/* The transfer phase returned error, we mark the connection to get
* closed to prevent being re-used. This is becasue we can't
* possibly know if the connection is in a good shape or not now. */
easy->easy_conn->bits.close = TRUE;
if(-1 !=easy->easy_conn->secondarysocket) {
/* if we failed anywhere, we must clean up the secondary socket if
it was used */
sclose(easy->easy_conn->secondarysocket);
easy->easy_conn->secondarysocket=-1;
}
Curl_posttransfer(easy->easy_handle);
Curl_done(easy->easy_conn);
}
/* after the transfer is done, go DONE */
else if(TRUE == done) {
/* call this even if the readwrite function returned error */
Curl_posttransfer(easy->easy_handle);
/* When we follow redirects, must to go back to the CONNECT state */
if(easy->easy_conn->newurl) {
easy->result = Curl_follow(easy->easy_handle,
strdup(easy->easy_conn->newurl));
if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_CONNECT;
easy->state = CURLM_STATE_PERFORM;
result = CURLM_CALL_MULTI_PERFORM;
}
}
else {
easy->state = CURLM_STATE_DONE;
result = CURLM_CALL_MULTI_PERFORM;
break;
case CURLM_STATE_PERFORM:
/* read/write data if it is ready to do so */
easy->result = Curl_readwrite(easy->easy_conn, &done);
if(easy->result) {
/* The transfer phase returned error, we mark the connection to get
* closed to prevent being re-used. This is becasue we can't
* possibly know if the connection is in a good shape or not now. */
easy->easy_conn->bits.close = TRUE;
if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) {
/* if we failed anywhere, we must clean up the secondary socket if
it was used */
sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
easy->easy_conn->sock[SECONDARYSOCKET]=-1;
}
Curl_posttransfer(easy->easy_handle);
Curl_done(&easy->easy_conn, easy->result);
}
}
break;
case CURLM_STATE_DONE:
/* post-transfer command */
easy->result = Curl_done(easy->easy_conn);
/* after we have DONE what we're supposed to do, go COMPLETED, and
it doesn't matter what the Curl_done() returned! */
easy->state = CURLM_STATE_COMPLETED;
break;
/* after the transfer is done, go DONE */
else if(TRUE == done) {
case CURLM_STATE_COMPLETED:
/* this is a completed transfer, it is likely to still be connected */
/* call this even if the readwrite function returned error */
Curl_posttransfer(easy->easy_handle);
/* This node should be delinked from the list now and we should post
an information message that we are complete. */
break;
default:
return CURLM_INTERNAL_ERROR;
}
/* When we follow redirects, must to go back to the CONNECT state */
if(easy->easy_conn->newurl) {
char *newurl = easy->easy_conn->newurl;
easy->easy_conn->newurl = NULL;
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
if(easy->result == CURLE_OK)
easy->result = Curl_follow(easy->easy_handle, newurl);
if(CURLE_OK == easy->result) {
easy->state = CURLM_STATE_CONNECT;
result = CURLM_CALL_MULTI_PERFORM;
}
}
else {
easy->state = CURLM_STATE_DONE;
result = CURLM_CALL_MULTI_PERFORM;
}
}
break;
case CURLM_STATE_DONE:
/* post-transfer command */
easy->result = Curl_done(&easy->easy_conn, CURLE_OK);
if(CURLM_STATE_COMPLETED != easy->state) {
if(CURLE_OK != easy->result)
/*
* If an error was returned, and we aren't in completed state now,
* then we go to completed and consider this transfer aborted. */
/* after we have DONE what we're supposed to do, go COMPLETED, and
it doesn't matter what the Curl_done() returned! */
easy->state = CURLM_STATE_COMPLETED;
else
/* this one still lives! */
(*running_handles)++;
}
break;
case CURLM_STATE_COMPLETED:
/* this is a completed transfer, it is likely to still be connected */
/* This node should be delinked from the list now and we should post
an information message that we are complete. */
break;
default:
return CURLM_INTERNAL_ERROR;
}
if(CURLM_STATE_COMPLETED != easy->state) {
if(CURLE_OK != easy->result) {
/*
* If an error was returned, and we aren't in completed state now,
* then we go to completed and consider this transfer aborted. */
easy->state = CURLM_STATE_COMPLETED;
}
else
/* this one still lives! */
(*running_handles)++;
}
} while (easy->easy_handle->change.url_changed);
if ((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) {
/* clear out the usage of the shared DNS cache */
@ -535,9 +619,11 @@ CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
*msgs_in_queue = 0; /* default to none */
if(GOOD_MULTI_HANDLE(multi)) {
struct Curl_one_easy *easy;
if(!multi->num_msgs)
return NULL; /* no messages left to return */
@ -560,11 +646,3 @@ CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
else
return NULL;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -41,14 +41,17 @@
#endif
#include <curl/curl.h>
#include "netrc.h"
#include "strequal.h"
#include "strtok.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* Debug this single source file with:
'make netrc' then run './netrc'!
@ -71,56 +74,27 @@ enum {
#define LOGINSIZE 64
#define PASSWORDSIZE 64
/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
int Curl_parsenetrc(char *host,
char *login,
char *password)
char *password,
char *netrcfile)
{
FILE *file;
char netrcbuffer[256];
int retcode=1;
int specific_login = (login[0] != 0);
char *home = NULL;
bool home_alloc = FALSE;
bool netrc_alloc = FALSE;
int state=NOTHING;
char state_login=0; /* Found a login keyword */
char state_password=0; /* Found a password keyword */
char state_our_login=0; /* With specific_login, found *our* login name */
int state_our_login=FALSE; /* With specific_login, found *our* login name */
#define NETRC DOT_CHAR "netrc"
#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
struct passwd *pw;
pw= getpwuid(geteuid());
if (pw) {
#ifdef VMS
/* VMS does not work because of warnings on icc */
/* home = decc$translate_vms(pw->pw_dir); */
#else
home = pw->pw_dir;
#endif
}
#else
void *pw=NULL;
#endif
if(NULL == pw) {
home = curl_getenv("HOME"); /* portable environment reader */
if(!home) {
return -1;
}
}
if(strlen(home)>(sizeof(netrcbuffer)-strlen(NETRC))) {
if(NULL==pw)
free(home);
return -1;
}
sprintf(netrcbuffer, "%s%s%s", home, DIR_CHAR, NETRC);
#ifdef MALLOCDEBUG
#ifdef CURLDEBUG
{
/* This is a hack to allow testing.
* If compiled with --enable-debug and CURL_DEBUG_NETRC is defined,
@ -128,32 +102,59 @@ int Curl_parsenetrc(char *host,
char *override = curl_getenv("CURL_DEBUG_NETRC");
if (override != NULL) {
printf("NETRC: overridden .netrc file: %s\n", home);
if (strlen(override)+1 > sizeof(netrcbuffer)) {
free(override);
if(NULL==pw)
free(home);
return -1;
}
strcpy(netrcbuffer, override);
free(override);
if (override) {
printf("NETRC: overridden " NETRC " file: %s\n", home);
netrcfile = override;
netrc_alloc = TRUE;
}
}
#endif /* MALLOCDEBUG */
#endif /* CURLDEBUG */
if(!netrcfile) {
home = curl_getenv("HOME"); /* portable environment reader */
if(home) {
home_alloc = TRUE;
#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
}
else {
struct passwd *pw;
pw= getpwuid(geteuid());
if (pw) {
#ifdef VMS
home = decc$translate_vms(pw->pw_dir);
#else
home = pw->pw_dir;
#endif
}
#endif
}
file = fopen(netrcbuffer, "r");
if(!home)
return -1;
netrcfile = curl_maprintf("%s%s%s", home, DIR_CHAR, NETRC);
if(!netrcfile) {
if(home_alloc)
free(home);
return -1;
}
netrc_alloc = TRUE;
}
file = fopen(netrcfile, "r");
if(file) {
char *tok;
char *tok_buf;
while(fgets(netrcbuffer, sizeof(netrcbuffer), file)) {
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
while(tok) {
char *tok_buf;
bool done=FALSE;
char netrcbuffer[256];
if (login[0] && password[0])
goto done;
while(!done && fgets(netrcbuffer, sizeof(netrcbuffer), file)) {
tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
while(!done && tok) {
if (login[0] && password[0]) {
done=TRUE;
break;
}
switch(state) {
case NOTHING:
@ -182,8 +183,9 @@ int Curl_parsenetrc(char *host,
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if (specific_login) {
state_our_login = (char)strequal(login, tok);
}else{
state_our_login = strequal(login, tok);
}
else {
strncpy(login, tok, LOGINSIZE-1);
#ifdef _NETRC_DEBUG
printf("LOGIN: %s\n", login);
@ -207,7 +209,7 @@ int Curl_parsenetrc(char *host,
else if(strequal("machine", tok)) {
/* ok, there's machine here go => */
state = HOSTFOUND;
state_our_login = 0;
state_our_login = FALSE;
}
break;
} /* switch (state) */
@ -216,12 +218,13 @@ int Curl_parsenetrc(char *host,
} /* while (tok) */
} /* while fgets() */
done:
fclose(file);
}
if(NULL==pw)
if(home_alloc)
free(home);
if(netrc_alloc)
free(netrcfile);
return retcode;
}
@ -242,11 +245,3 @@ int main(int argc, char **argv)
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -24,7 +24,8 @@
***************************************************************************/
int Curl_parsenetrc(char *host,
char *login,
char *password);
char *password,
char *filename);
/* Assume: password[0]=0, host[0] != 0.
* If login[0] = 0, search for login and password within a machine section
* in the netrc.

300
Source/CTest/Curl/nwlib.c Normal file
View File

@ -0,0 +1,300 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <library.h>
#include <netware.h>
#include <screen.h>
#include <nks/thread.h>
#include <nks/synch.h>
#include "memory.h"
#include "memdebug.h"
typedef struct
{
int _errno;
void *twentybytes;
} libthreaddata_t;
typedef struct
{
int x;
int y;
int z;
void *tenbytes;
NXKey_t perthreadkey; /* if -1, no key obtained... */
NXMutex_t *lock;
} libdata_t;
int gLibId = -1;
void *gLibHandle = (void *) NULL;
rtag_t gAllocTag = (rtag_t) NULL;
NXMutex_t *gLibLock = (NXMutex_t *) NULL;
/* internal library function prototypes... */
int DisposeLibraryData ( void * );
void DisposeThreadData ( void * );
int GetOrSetUpData ( int id, libdata_t **data, libthreaddata_t **threaddata );
int _NonAppStart( void *NLMHandle,
void *errorScreen,
const char *cmdLine,
const char *loadDirPath,
size_t uninitializedDataLength,
void *NLMFileHandle,
int (*readRoutineP)( int conn,
void *fileHandle, size_t offset,
size_t nbytes,
size_t *bytesRead,
void *buffer ),
size_t customDataOffset,
size_t customDataSize,
int messageCount,
const char **messages )
{
NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
#ifndef __GNUC__
#pragma unused(cmdLine)
#pragma unused(loadDirPath)
#pragma unused(uninitializedDataLength)
#pragma unused(NLMFileHandle)
#pragma unused(readRoutineP)
#pragma unused(customDataOffset)
#pragma unused(customDataSize)
#pragma unused(messageCount)
#pragma unused(messages)
#endif
/*
** Here we process our command line, post errors (to the error screen),
** perform initializations and anything else we need to do before being able
** to accept calls into us. If we succeed, we return non-zero and the NetWare
** Loader will leave us up, otherwise we fail to load and get dumped.
*/
gAllocTag = AllocateResourceTag(NLMHandle,
"<library-name> memory allocations",
AllocSignature);
if (!gAllocTag) {
OutputToScreen(errorScreen, "Unable to allocate resource tag for "
"library memory allocations.\n");
return -1;
}
gLibId = register_library(DisposeLibraryData);
if (gLibId < -1) {
OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
return -1;
}
gLibHandle = NLMHandle;
gLibLock = NXMutexAlloc(0, 0, &liblock);
if (!gLibLock) {
OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
return -1;
}
return 0;
}
/*
** Here we clean up any resources we allocated. Resource tags is a big part
** of what we created, but NetWare doesn't ask us to free those.
*/
void _NonAppStop( void )
{
(void) unregister_library(gLibId);
NXMutexFree(gLibLock);
}
/*
** This function cannot be the first in the file for if the file is linked
** first, then the check-unload function's offset will be nlmname.nlm+0
** which is how to tell that there isn't one. When the check function is
** first in the linked objects, it is ambiguous. For this reason, we will
** put it inside this file after the stop function.
**
** Here we check to see if it's alright to ourselves to be unloaded. If not,
** we return a non-zero value. Right now, there isn't any reason not to allow
** it.
*/
int _NonAppCheckUnload( void )
{
return 0;
}
int GetOrSetUpData(int id, libdata_t **appData,
libthreaddata_t **threadData )
{
int err;
libdata_t *app_data;
libthreaddata_t *thread_data;
NXKey_t key;
NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
err = 0;
thread_data = (libthreaddata_t *) NULL;
/*
** Attempt to get our data for the application calling us. This is where we
** store whatever application-specific information we need to carry in support
** of calling applications.
*/
app_data = (libdata_t *) get_app_data(id);
if (!app_data) {
/*
** This application hasn't called us before; set up application AND per-thread
** data. Of course, just in case a thread from this same application is calling
** us simultaneously, we better lock our application data-creation mutex. We
** also need to recheck for data after we acquire the lock because WE might be
** that other thread that was too late to create the data and the first thread
** in will have created it.
*/
NXLock(gLibLock);
if (!(app_data = (libdata_t *) get_app_data(id))) {
app_data = (libdata_t *) malloc(sizeof(libdata_t));
if (app_data) {
memset(app_data, 0, sizeof(libdata_t));
app_data->tenbytes = malloc(10);
app_data->lock = NXMutexAlloc(0, 0, &liblock);
if (!app_data->tenbytes || !app_data->lock) {
if (app_data->lock)
NXMutexFree(app_data->lock);
free(app_data);
app_data = (libdata_t *) NULL;
err = ENOMEM;
}
if (app_data) {
/*
** Here we burn in the application data that we were trying to get by calling
** get_app_data(). Next time we call the first function, we'll get this data
** we're just now setting. We also go on here to establish the per-thread data
** for the calling thread, something we'll have to do on each application
** thread the first time it calls us.
*/
err = set_app_data(gLibId, app_data);
if (err) {
free(app_data);
app_data = (libdata_t *) NULL;
err = ENOMEM;
}
else {
/* create key for thread-specific data... */
err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
if (err) /* (no more keys left?) */
key = -1;
app_data->perthreadkey = key;
}
}
}
}
NXUnlock(gLibLock);
}
if (app_data) {
key = app_data->perthreadkey;
if (key != -1 /* couldn't create a key? no thread data */
&& !(err = NXKeyGetValue(key, (void **) &thread_data))
&& !thread_data) {
/*
** Allocate the per-thread data for the calling thread. Regardless of whether
** there was already application data or not, this may be the first call by a
** a new thread. The fact that we allocation 20 bytes on a pointer is not very
** important, this just helps to demonstrate that we can have arbitrarily
** complex per-thread data.
*/
thread_data = (libthreaddata_t *) malloc(sizeof(libthreaddata_t));
if (thread_data) {
thread_data->_errno = 0;
thread_data->twentybytes = malloc(20);
if (!thread_data->twentybytes) {
free(thread_data);
thread_data = (libthreaddata_t *) NULL;
err = ENOMEM;
}
if ((err = NXKeySetValue(key, thread_data))) {
free(thread_data->twentybytes);
free(thread_data);
thread_data = (libthreaddata_t *) NULL;
}
}
}
}
if (appData)
*appData = app_data;
if (threadData)
*threadData = thread_data;
return err;
}
int DisposeLibraryData( void *data)
{
if (data) {
void *tenbytes = ((libdata_t *) data)->tenbytes;
if (tenbytes)
free(tenbytes);
free(data);
}
return 0;
}
void DisposeThreadData(void *data)
{
if (data) {
void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
if (twentybytes)
free(twentybytes);
free(data);
}
}

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -24,17 +24,8 @@
#include "setup.h"
#include <string.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#if defined(__MINGW32__)
#include <winsock.h>
#endif
#include <time.h>
#endif
/* 20000318 mgs
* later we use _scrsize to determine the screen width, this emx library
* function needs stdlib.h to be included */
#if defined(__EMX__)
#include <stdlib.h>
#endif
@ -42,46 +33,94 @@
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#include "progress.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
static void time2str(char *r, int t)
/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
byte) */
static void time2str(char *r, long t)
{
int h = (t/3600);
int m = (t-(h*3600))/60;
int s = (t-(h*3600)-(m*60));
sprintf(r,"%2d:%02d:%02d",h,m,s);
long h;
if(!t) {
strcpy(r, "--:--:--");
return;
}
h = (t/3600);
if(h <= 99) {
long m = (t-(h*3600))/60;
long s = (t-(h*3600)-(m*60));
snprintf(r, 9, "%2ld:%02ld:%02ld",h,m,s);
}
else {
/* this equals to more than 99 hours, switch to a more suitable output
format to fit within the limits. */
if(h/24 <= 999)
snprintf(r, 9, "%3ldd %02ldh", h/24, h-(h/24)*24);
else
snprintf(r, 9, "%7ldd", h/24);
}
}
/* The point of this function would be to return a string of the input data,
but never longer than 5 columns. Add suffix k, M, G when suitable... */
static char *max5data(double bytes, char *max5)
but never longer than 5 columns (+ one zero byte).
Add suffix k, M, G when suitable... */
static char *max5data(curl_off_t bytes, char *max5)
{
#define ONE_KILOBYTE 1024
#define ONE_MEGABYTE (1024*1024)
#define ONE_MEGABYTE (1024* ONE_KILOBYTE)
#define ONE_GIGABYTE (1024* ONE_MEGABYTE)
#define ONE_TERRABYTE ((curl_off_t)1024* ONE_GIGABYTE)
#define ONE_PETABYTE ((curl_off_t)1024* ONE_TERRABYTE)
if(bytes < 100000) {
sprintf(max5, "%5d", (int)bytes);
return max5;
snprintf(max5, 6, "%5" FORMAT_OFF_T, bytes);
}
if(bytes < (9999*ONE_KILOBYTE)) {
sprintf(max5, "%4dk", (int)bytes/ONE_KILOBYTE);
return max5;
else if(bytes < (10000*ONE_KILOBYTE)) {
snprintf(max5, 6, "%4" FORMAT_OFF_T "k", (curl_off_t)(bytes/ONE_KILOBYTE));
}
if(bytes < (100*ONE_MEGABYTE)) {
else if(bytes < (100*ONE_MEGABYTE)) {
/* 'XX.XM' is good as long as we're less than 100 megs */
sprintf(max5, "%4.1fM", bytes/ONE_MEGABYTE);
return max5;
snprintf(max5, 6, "%2d.%0dM",
(int)(bytes/ONE_MEGABYTE),
(int)(bytes%ONE_MEGABYTE)/(ONE_MEGABYTE/10) );
}
sprintf(max5, "%4dM", (int)bytes/ONE_MEGABYTE);
#if SIZEOF_CURL_OFF_T > 4
else if(bytes < ( (curl_off_t)10000*ONE_MEGABYTE))
/* 'XXXXM' is good until we're at 10000MB or above */
snprintf(max5, 6, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE));
else if(bytes < (curl_off_t)100*ONE_GIGABYTE)
/* 10000 MB - 100 GB, we show it as XX.XG */
snprintf(max5, 6, "%2d.%0dG",
(int)(bytes/ONE_GIGABYTE),
(int)(bytes%ONE_GIGABYTE)/(ONE_GIGABYTE/10) );
else if(bytes < (curl_off_t)10000 * ONE_GIGABYTE)
/* up to 10000GB, display without decimal: XXXXG */
snprintf(max5, 6, "%4dG", (int)(bytes/ONE_GIGABYTE));
else if(bytes < (curl_off_t)10000 * ONE_TERRABYTE)
/* up to 10000TB, display without decimal: XXXXT */
snprintf(max5, 6, "%4dT", (int)(bytes/ONE_TERRABYTE));
else {
/* up to 10000PB, display without decimal: XXXXP */
snprintf(max5, 6, "%4dP", (int)(bytes/ONE_PETABYTE));
/* 16384 petabytes (16 exabytes) is maximum a 64 bit number can hold,
but this type is signed so 8192PB will be max.*/
}
#else
else
snprintf(max5, 6, "%4" FORMAT_OFF_T "M", (curl_off_t)(bytes/ONE_MEGABYTE));
#endif
return max5;
}
/*
/*
New proposed interface, 9th of February 2000:
@ -98,13 +137,12 @@ static char *max5data(double bytes, char *max5)
void Curl_pgrsDone(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
if(!(data->progress.flags & PGRS_HIDE)) {
data->progress.lastshow=0;
Curl_pgrsUpdate(conn); /* the final (forced) update */
if(!data->progress.callback)
/* only output if we don't use progress callback */
fprintf(data->set.err, "\n");
}
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");
}
/* reset all times except redirect */
@ -130,26 +168,26 @@ void Curl_pgrsTime(struct SessionHandle *data, timerid timer)
case TIMER_NAMELOOKUP:
data->progress.t_nslookup =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0;
Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break;
case TIMER_CONNECT:
data->progress.t_connect =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0;
Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break;
case TIMER_PRETRANSFER:
data->progress.t_pretransfer =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0;
Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break;
case TIMER_STARTTRANSFER:
data->progress.t_starttransfer =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle)/1000.0;
Curl_tvdiff_secs(Curl_tvnow(), data->progress.t_startsingle);
break;
case TIMER_POSTRANSFER:
/* this is the normal end-of-transfer thing */
break;
case TIMER_REDIRECT:
data->progress.t_redirect =
(double)Curl_tvdiff(Curl_tvnow(), data->progress.start)/1000.0;
Curl_tvdiff_secs(Curl_tvnow(), data->progress.start);
break;
}
}
@ -160,70 +198,55 @@ void Curl_pgrsStartNow(struct SessionHandle *data)
data->progress.start = Curl_tvnow();
}
void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, double size)
void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size)
{
data->progress.downloaded = size;
}
void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size)
void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size)
{
data->progress.uploaded = size;
}
void Curl_pgrsSetDownloadSize(struct SessionHandle *data, double size)
void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size)
{
if(size > 0) {
data->progress.size_dl = size;
data->progress.size_dl = size;
if(size > 0)
data->progress.flags |= PGRS_DL_SIZE_KNOWN;
}
else
data->progress.flags &= ~PGRS_DL_SIZE_KNOWN;
}
void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size)
void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size)
{
if(size > 0) {
data->progress.size_ul = size;
data->progress.size_ul = size;
if(size > 0)
data->progress.flags |= PGRS_UL_SIZE_KNOWN;
}
else
data->progress.flags &= ~PGRS_UL_SIZE_KNOWN;
}
/* EXAMPLE OUTPUT to follow:
% Total % Received % Xferd Average Speed Time Curr.
Dload Upload Total Current Left Speed
100 12345 100 12345 100 12345 12345 12345 12:12:12 12:12:12 12:12:12 12345
*/
int Curl_pgrsUpdate(struct connectdata *conn)
{
struct timeval now;
int result;
char max5[6][10];
double dlpercen=0;
double ulpercen=0;
double total_percen=0;
double total_transfer;
double total_expected_transfer;
double timespent;
int dlpercen=0;
int ulpercen=0;
int total_percen=0;
curl_off_t total_transfer;
curl_off_t total_expected_transfer;
long timespent;
struct SessionHandle *data = conn->data;
int nowindex = data->progress.speeder_c% CURR_TIME;
int checkindex;
int countindex; /* amount of seconds stored in the speeder array */
char time_left[10];
char time_total[10];
char time_current[10];
double ulestimate=0;
double dlestimate=0;
double total_estimate;
char time_spent[10];
long ulestimate=0;
long dlestimate=0;
long total_estimate;
if(data->progress.flags & PGRS_HIDE)
; /* We do enter this function even if we don't wanna see anything, since
@ -232,32 +255,35 @@ int Curl_pgrsUpdate(struct connectdata *conn)
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if (!data->progress.callback) {
if(conn->resume_from)
fprintf(data->set.err, "** Resuming transfer from byte position %d\n",
fprintf(data->set.err,
"** Resuming transfer from byte position %" FORMAT_OFF_T
"\n",
conn->resume_from);
fprintf(data->set.err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload Upload Total Current Left Speed\n");
" %% Total %% Received %% Xferd Average Speed Time Time Time Current\n"
" Dload Upload Total Spent Left Speed\n");
}
data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */
}
now = Curl_tvnow(); /* what time is it */
/* The exact time spent so far (from the start) */
timespent = (double)Curl_tvdiff (now, data->progress.start)/1000;
data->progress.timespent = timespent;
/* The time spent so far (from the start) */
data->progress.timespent = Curl_tvdiff_secs(now, data->progress.start);
timespent = (long)data->progress.timespent;
/* The average download speed this far */
data->progress.dlspeed =
data->progress.downloaded/(timespent>0.01?timespent:1);
data->progress.dlspeed = (curl_off_t)
((double)data->progress.downloaded/
(data->progress.timespent>0?data->progress.timespent:1));
/* The average upload speed this far */
data->progress.ulspeed =
data->progress.uploaded/(timespent>0.01?timespent:1);
data->progress.ulspeed = (curl_off_t)
((double)data->progress.uploaded/
(data->progress.timespent>0?data->progress.timespent:1));
if(data->progress.lastshow == Curl_tvlong(now))
return 0; /* never update this more than once a second if the end isn't
return 0; /* never update this more than once a second if the end isn't
reached */
data->progress.lastshow = now.tv_sec;
@ -297,10 +323,21 @@ int Curl_pgrsUpdate(struct connectdata *conn)
if(0 == span_ms)
span_ms=1; /* at least one millisecond MUST have passed */
/* Calculate the average speed the last 'countindex' seconds */
data->progress.current_speed =
(data->progress.speeder[nowindex]-
data->progress.speeder[checkindex])/((double)span_ms/1000);
/* Calculate the average speed the last 'span_ms' milliseconds */
{
curl_off_t amount = data->progress.speeder[nowindex]-
data->progress.speeder[checkindex];
if(amount > 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)
((double)amount/((double)span_ms/1000.0));
else
/* the 'amount' value is small enough to fit within 32 bits even
when multiplied with 1000 */
data->progress.current_speed = amount*1000/span_ms;
}
}
else
/* the first second we use the main average */
@ -315,74 +352,70 @@ int Curl_pgrsUpdate(struct connectdata *conn)
/* There's a callback set, so we call that instead of writing
anything ourselves. This really is the way to go. */
result= data->set.fprogress(data->set.progress_client,
data->progress.size_dl,
data->progress.downloaded,
data->progress.size_ul,
data->progress.uploaded);
(double)data->progress.size_dl,
(double)data->progress.downloaded,
(double)data->progress.size_ul,
(double)data->progress.uploaded);
if(result)
failf(data, "Callback aborted");
return result;
}
/* Figure out the estimated time of arrival for the upload */
if((data->progress.flags & PGRS_UL_SIZE_KNOWN) && data->progress.ulspeed){
ulestimate = data->progress.size_ul / data->progress.ulspeed;
ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
if((data->progress.flags & PGRS_UL_SIZE_KNOWN) &&
(data->progress.ulspeed>0) &&
(data->progress.size_ul > 100) ) {
ulestimate = (long)(data->progress.size_ul / data->progress.ulspeed);
ulpercen = (int)(100*(data->progress.uploaded/100) /
(data->progress.size_ul/100) );
}
/* ... and the download */
if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && data->progress.dlspeed) {
dlestimate = data->progress.size_dl / data->progress.dlspeed;
dlpercen = (data->progress.downloaded / data->progress.size_dl)*100;
if((data->progress.flags & PGRS_DL_SIZE_KNOWN) &&
(data->progress.dlspeed>0) &&
(data->progress.size_dl>100)) {
dlestimate = (long)(data->progress.size_dl / data->progress.dlspeed);
dlpercen = (int)(100*(data->progress.downloaded/100) /
(data->progress.size_dl/100));
}
/* Now figure out which of them that is slower and use for the for
total estimate! */
total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
/* If we have a total estimate, we can display that and the expected
time left */
if(total_estimate) {
time2str(time_left, (int)(total_estimate - data->progress.timespent));
time2str(time_total, (int)total_estimate);
}
else {
/* otherwise we blank those times */
strcpy(time_left, "--:--:--");
strcpy(time_total, "--:--:--");
}
/* The time spent so far is always known */
time2str(time_current, (int)data->progress.timespent);
/* create the three time strings */
time2str(time_left, total_estimate > 0?(total_estimate - timespent):0);
time2str(time_total, total_estimate);
time2str(time_spent, timespent);
/* Get the total amount of data expected to get transfered */
total_expected_transfer =
total_expected_transfer =
(data->progress.flags & PGRS_UL_SIZE_KNOWN?
data->progress.size_ul:data->progress.uploaded)+
(data->progress.flags & PGRS_DL_SIZE_KNOWN?
data->progress.size_dl:data->progress.downloaded);
/* We have transfered this much so far */
total_transfer = data->progress.downloaded + data->progress.uploaded;
/* Get the percentage of data transfered so far */
if(total_expected_transfer)
total_percen=(double)(total_transfer/total_expected_transfer)*100;
if(total_expected_transfer > 100)
total_percen=(int)(100*(total_transfer/100) /
(total_expected_transfer/100) );
fprintf(data->set.err,
"\r%3d %s %3d %s %3d %s %s %s %s %s %s %s",
(int)total_percen, /* total % */
total_percen, /* 3 letters */ /* total % */
max5data(total_expected_transfer, max5[2]), /* total size */
(int)dlpercen, /* rcvd % */
dlpercen, /* 3 letters */ /* rcvd % */
max5data(data->progress.downloaded, max5[0]), /* rcvd size */
(int)ulpercen, /* xfer % */
ulpercen, /* 3 letters */ /* xfer % */
max5data(data->progress.uploaded, max5[1]), /* xfer size */
max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */
max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */
time_total, /* total time */
time_current, /* current time */
time_left, /* time left */
max5data(data->progress.dlspeed, max5[3]), /* avrg dl speed */
max5data(data->progress.ulspeed, max5[4]), /* avrg ul speed */
time_total, /* 8 letters */ /* total time */
time_spent, /* 8 letters */ /* time spent */
time_left, /* 8 letters */ /* time left */
max5data(data->progress.current_speed, max5[5]) /* current speed */
);
@ -391,11 +424,3 @@ int Curl_pgrsUpdate(struct connectdata *conn)
return 0;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -40,10 +40,10 @@ typedef enum {
void Curl_pgrsDone(struct connectdata *);
void Curl_pgrsStartNow(struct SessionHandle *data);
void Curl_pgrsSetDownloadSize(struct SessionHandle *data, double size);
void Curl_pgrsSetUploadSize(struct SessionHandle *data, double size);
void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, double size);
void Curl_pgrsSetUploadCounter(struct SessionHandle *data, double size);
void Curl_pgrsSetDownloadSize(struct SessionHandle *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct SessionHandle *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct SessionHandle *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct SessionHandle *data, curl_off_t size);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTimes(struct SessionHandle *data);
void Curl_pgrsTime(struct SessionHandle *data, timerid timer);

View File

@ -10,22 +10,22 @@
* Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@ -41,7 +41,7 @@
#include "setup.h"
#ifndef CURL_DISABLE_FTP
#ifdef KRB4
#ifdef HAVE_KRB4
#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
#include <curl/mprintf.h>
@ -58,11 +58,10 @@
#include "base64.h"
#include "sendf.h"
#include "ftp.h"
#include "memory.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#define min(a, b) ((a) < (b) ? (a) : (b))
@ -76,7 +75,7 @@ static struct {
{ prot_private, "private" }
};
static enum protection_level
static enum protection_level
name_to_level(const char *name)
{
int i;
@ -90,7 +89,7 @@ static struct Curl_sec_client_mech *mechs[] = {
#ifdef KRB5
/* not supported */
#endif
#ifdef KRB4
#ifdef HAVE_KRB4
&Curl_krb4_client_mech,
#endif
NULL
@ -147,7 +146,7 @@ sec_get_data(struct connectdata *conn,
{
int len;
int b;
b = block_read(fd, &len, sizeof(len));
if (b == 0)
return 0;
@ -207,12 +206,12 @@ Curl_sec_read(struct connectdata *conn, int fd, void *buffer, int length)
conn->in_buffer.eof_flag = 0;
return 0;
}
len = buffer_read(&conn->in_buffer, buffer, length);
length -= len;
rx += len;
buffer = (char*)buffer + len;
while(length) {
if(sec_get_data(conn, fd, &conn->in_buffer) < 0)
return -1;
@ -262,7 +261,7 @@ Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length)
{
int len = conn->buffer_size;
int tx = 0;
if(conn->data_prot == prot_clear)
return write(fd, buffer, length);
@ -284,7 +283,7 @@ Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
char ch = c;
if(conn->data_prot == prot_clear)
return putc(c, F);
buffer_write(&conn->out_buffer, &ch, 1);
if(c == '\n' || conn->out_buffer.index >= 1024 /* XXX */) {
Curl_sec_write(conn, fileno(F), conn->out_buffer.data,
@ -297,36 +296,38 @@ Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
int
Curl_sec_read_msg(struct connectdata *conn, char *s, int level)
{
int len;
char *buf;
int code;
buf = malloc(strlen(s));
len = Curl_base64_decode(s + 4, buf); /* XXX */
len = (conn->mech->decode)(conn->app_data, buf, len, level, conn);
if(len < 0)
return -1;
buf[len] = '\0';
int len;
char *buf;
int code;
if(buf[3] == '-')
code = 0;
else
sscanf(buf, "%d", &code);
if(buf[len-1] == '\n')
buf[len-1] = '\0';
strcpy(s, buf);
buf = malloc(strlen(s));
len = Curl_base64_decode(s + 4, buf); /* XXX */
len = (conn->mech->decode)(conn->app_data, buf, len, level, conn);
if(len < 0) {
free(buf);
return code;
return -1;
}
buf[len] = '\0';
if(buf[3] == '-')
code = 0;
else
sscanf(buf, "%d", &code);
if(buf[len-1] == '\n')
buf[len-1] = '\0';
strcpy(s, buf);
free(buf);
return code;
}
enum protection_level
Curl_set_command_prot(struct connectdata *conn, enum protection_level level)
{
enum protection_level old = conn->command_prot;
conn->command_prot = level;
return old;
enum protection_level old = conn->command_prot;
conn->command_prot = level;
return old;
}
static int
@ -372,7 +373,7 @@ sec_prot_internal(struct connectdata *conn, int level)
failf(conn->data, "Failed to set protection level.");
return -1;
}
conn->data_prot = (enum protection_level)level;
return 0;
}
@ -413,7 +414,7 @@ Curl_sec_login(struct connectdata *conn)
return -1;
}
conn->app_data = tmp;
if((*m)->init && (*(*m)->init)(conn->app_data) != 0) {
infof(data, "Skipping %s...\n", (*m)->name);
continue;
@ -447,7 +448,7 @@ Curl_sec_login(struct connectdata *conn)
}
ret = (*(*m)->auth)(conn->app_data, conn);
if(ret == AUTH_CONTINUE)
continue;
else if(ret != AUTH_OK){
@ -459,7 +460,7 @@ Curl_sec_login(struct connectdata *conn)
conn->command_prot = prot_safe;
break;
}
return *m == NULL;
}
@ -478,13 +479,5 @@ Curl_sec_end(struct connectdata *conn)
conn->mech=NULL;
}
#endif /* KRB4 */
#endif /* HAVE_KRB4 */
#endif /* CURL_DISABLE_FTP */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -39,25 +39,22 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#include "connect.h" /* for the Curl_ourerrno() proto */
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
#ifdef KRB4
#ifdef HAVE_KRB4
#include "security.h"
#endif
#include <string.h>
#include "memory.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
@ -76,11 +73,13 @@ static struct curl_slist *slist_get_last(struct curl_slist *list)
return item;
}
/* append a struct to the linked list. It always retunrs the address of the
* first record, so that you can sure this function as an initialization
* function as well as an append function. If you find this bothersome,
* then simply create a separate _init function and call it appropriately from
* within the proram. */
/*
* curl_slist_append() appends a string to the linked list. It always retunrs
* the address of the first record, so that you can sure this function as an
* initialization function as well as an append function. If you find this
* bothersome, then simply create a separate _init function and call it
* appropriately from within the proram.
*/
struct curl_slist *curl_slist_append(struct curl_slist *list,
const char *data)
{
@ -89,13 +88,18 @@ struct curl_slist *curl_slist_append(struct curl_slist *list,
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
new_item->next = NULL;
new_item->data = strdup(data);
char *dup = strdup(data);
if(dup) {
new_item->next = NULL;
new_item->data = dup;
}
else {
free(new_item);
return NULL;
}
}
if (new_item == NULL || new_item->data == NULL) {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
else
return NULL;
}
if (list) {
last = slist_get_last(list);
@ -119,7 +123,7 @@ void curl_slist_free_all(struct curl_slist *list)
item = list;
do {
next = item->next;
if (item->data) {
free(item->data);
}
@ -132,13 +136,13 @@ void curl_slist_free_all(struct curl_slist *list)
void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
{
va_list ap;
if(data->set.verbose) {
if(data && data->set.verbose) {
va_list ap;
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));
Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer), NULL);
}
}
@ -155,14 +159,14 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
data->state.errorbuf = TRUE; /* wrote error string */
if(data->set.verbose) {
int len = (int)strlen(data->set.errorbuffer);
size_t len = strlen(data->set.errorbuffer);
bool doneit=FALSE;
if(len < CURL_ERROR_SIZE) {
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);
Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len, NULL);
if(doneit)
/* cut off the newline again */
data->set.errorbuffer[--len]=0;
@ -172,12 +176,12 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
}
/* Curl_sendf() sends formated data to the server */
CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
const char *fmt, ...)
{
struct SessionHandle *data = conn->data;
ssize_t bytes_written;
ssize_t write_len;
size_t write_len;
CURLcode res;
char *s;
char *sptr;
@ -189,10 +193,10 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
return CURLE_OUT_OF_MEMORY; /* failure */
bytes_written=0;
write_len = (int)strlen(s);
write_len = strlen(s);
sptr = s;
do {
while (1) {
/* Write the buffer to the socket */
res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
@ -200,9 +204,10 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
break;
if(data->set.verbose)
Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written);
Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written,
conn->host.dispname);
if(bytes_written != write_len) {
if((size_t)bytes_written != write_len) {
/* if not all was written at once, we must advance the pointer, decrease
the size left and try again! */
write_len -= bytes_written;
@ -210,8 +215,7 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
}
else
break;
} while(1);
}
free(s); /* free the output string */
@ -221,33 +225,51 @@ CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
/*
* Curl_write() is an internal write function that sends plain (binary) data
* to the server. Works with plain sockets, SSL or kerberos.
*
*/
CURLcode Curl_write(struct connectdata *conn, int sockfd,
void *mem, size_t len,
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,
void *mem,
size_t len,
ssize_t *written)
{
ssize_t bytes_written;
(void)conn;
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.use) {
if (conn->ssl[num].use) {
int err;
int rc = SSL_write(conn->ssl.handle, mem, len);
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.handle, rc);
err = SSL_get_error(conn->ssl[num].handle, rc);
switch(err) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* this is basicly the EWOULDBLOCK equivalent */
/* 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", errno);
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 */
@ -257,34 +279,44 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
bytes_written = rc;
}
else {
#else
(void)conn;
#endif
#ifdef KRB4
#ifdef HAVE_KRB4
if(conn->sec_complete) {
bytes_written = Curl_sec_write(conn, sockfd, mem, len);
}
else
#endif /* KRB4 */
#endif /* HAVE_KRB4 */
{
bytes_written = (int)swrite(sockfd, mem, (int)len);
bytes_written = (ssize_t)swrite(sockfd, mem, len);
}
if(-1 == bytes_written) {
#ifdef WIN32
if(WSAEWOULDBLOCK == GetLastError())
int err = Curl_ourerrno();
if(
#ifdef WSAEWOULDBLOCK
/* This is how Windows does it */
(WSAEWOULDBLOCK == err)
#else
if(EWOULDBLOCK == errno)
/* 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 */
*written=0;
return CURLE_OK;
}
bytes_written=0;
}
#ifdef USE_SSLEAY
}
#endif
*written = bytes_written;
return (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
return retcode;
}
/* client_write() sends data to the write callback(s)
@ -324,7 +356,7 @@ CURLcode Curl_client_write(struct SessionHandle *data,
return CURLE_WRITE_ERROR;
}
}
return CURLE_OK;
}
@ -335,23 +367,27 @@ CURLcode Curl_client_write(struct SessionHandle *data,
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
*/
int Curl_read(struct connectdata *conn,
int sockfd,
char *buf,
size_t buffersize,
ssize_t *n)
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 */
ssize_t *n) /* amount bytes read */
{
ssize_t nread;
*n=0; /* reset amount to zero */
(void)conn;
#ifdef USE_SSLEAY
if (conn->ssl.use) {
nread = SSL_read(conn->ssl.handle, buf, buffersize);
/* 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]);
*n=0; /* reset amount to zero */
if (conn->ssl[num].use) {
nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, (int)buffersize);
if(nread < 0) {
/* failed SSL_read */
int err = SSL_get_error(conn->ssl.handle, nread);
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
@ -362,25 +398,37 @@ int Curl_read(struct connectdata *conn,
/* there's data pending, re-invoke SSL_read() */
return -1; /* basicly EWOULDBLOCK */
default:
failf(conn->data, "SSL read error: %d", err);
/* 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;
}
}
}
else {
#else
(void)conn;
#endif
#ifdef KRB4
*n=0; /* reset amount to zero */
#ifdef HAVE_KRB4
if(conn->sec_complete)
nread = Curl_sec_read(conn, sockfd, buf, buffersize);
else
#endif
nread = sread (sockfd, buf, (int)buffersize);
nread = sread(sockfd, buf, buffersize);
if(-1 == nread) {
int err = Curl_ourerrno();
#ifdef WIN32
if(WSAEWOULDBLOCK == GetLastError())
if(WSAEWOULDBLOCK == err)
#else
if(EWOULDBLOCK == errno)
if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
#endif
return -1;
}
@ -393,11 +441,11 @@ int Curl_read(struct connectdata *conn,
}
/* return 0 on success */
int Curl_debug(struct SessionHandle *data, curl_infotype type,
char *ptr, size_t size)
static int showit(struct SessionHandle *data, curl_infotype type,
char *ptr, size_t size)
{
static const char * const s_infotype[CURLINFO_END] = {
"* ", "< ", "> ", "{ ", "} " };
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug)
return (*data->set.fdebug)(data, type, ptr, size,
@ -406,6 +454,7 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
case CURLINFO_HEADER_OUT:
case CURLINFO_HEADER_IN:
fwrite(s_infotype[type], 2, 1, data->set.err);
fwrite(ptr, size, 1, data->set.err);
break;
@ -415,11 +464,33 @@ int Curl_debug(struct SessionHandle *data, curl_infotype type,
return 0;
}
int Curl_debug(struct SessionHandle *data, curl_infotype type,
char *ptr, size_t size, char *host)
{
int rc;
if(data->set.printhost && host) {
char buffer[160];
const char *t=NULL;
switch (type) {
case CURLINFO_HEADER_IN:
case CURLINFO_DATA_IN:
t = "from";
break;
case CURLINFO_HEADER_OUT:
case CURLINFO_DATA_OUT:
t = "to";
break;
default:
break;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
if(t) {
snprintf(buffer, sizeof(buffer), "[Data %s %s]", t, host);
rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
if(rc)
return rc;
}
}
rc = showit(data, type, ptr, size);
return rc;
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -23,7 +23,8 @@
* $Id$
***************************************************************************/
CURLcode Curl_sendf(int fd, struct connectdata *, const char *fmt, ...);
CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *,
const char *fmt, ...);
void Curl_infof(struct SessionHandle *, const char *fmt, ...);
void Curl_failf(struct SessionHandle *, const char *fmt, ...);
@ -38,17 +39,18 @@ CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr,
size_t len);
/* internal read-function, does plain socket, SSL and krb4 */
int Curl_read(struct connectdata *conn, int sockfd,
int Curl_read(struct connectdata *conn, curl_socket_t sockfd,
char *buf, size_t buffersize,
ssize_t *n);
/* internal write-function, does plain socket, SSL and krb4 */
CURLcode Curl_write(struct connectdata *conn, int sockfd,
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,
void *mem, size_t len,
ssize_t *written);
/* the function used to output verbose information */
int Curl_debug(struct SessionHandle *handle, curl_infotype type,
char *data, size_t size);
char *data, size_t size, char *host);
#endif

View File

@ -1,18 +1,18 @@
#ifndef __SETUP_H
#define __SETUP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -23,9 +23,6 @@
* $Id$
***************************************************************************/
/* MN 06/07/02 */
/* #define HTTP_ONLY
*/
#ifdef HTTP_ONLY
#define CURL_DISABLE_FTP
#define CURL_DISABLE_LDAP
@ -35,35 +32,64 @@
#define CURL_DISABLE_GOPHER
#endif
#if !defined(WIN32) && (defined(__WIN32__) || defined(_WIN32))
#if !defined(WIN32) && defined(__WIN32__)
/* This should be a good Borland fix. Alexander J. Oss told us! */
#define WIN32
#endif
#ifdef HAVE_CONFIG_H
#ifdef VMS
#include "config-vms.h"
#else
#include "config.h" /* the configure script results */
#endif
#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
#ifndef __cplusplus /* (rabe) */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#if !defined(__cplusplus) && !defined(__BEOS__)
typedef unsigned char bool;
#define typedef_bool
#endif /* (rabe) */
#endif
#ifdef HAVE_LONGLONG
#define LONG_LONG long long
#define ENABLE_64BIT
#else
#ifdef _MSC_VER
#define LONG_LONG __int64
#define ENABLE_64BIT
#endif
#endif /* HAVE_LONGLONG */
#ifndef SIZEOF_CURL_OFF_T
/* If we don't know the size here, we assume a conservative size: 4. When
building libcurl, the actual size of this variable should be define in the
config*.h file. */
#define SIZEOF_CURL_OFF_T 4
#endif
/* We set up our internal prefered (CURL_)FORMAT_OFF_T here */
#if SIZEOF_CURL_OFF_T > 4
#define FORMAT_OFF_T "lld"
#else
#define FORMAT_OFF_T "ld"
#endif
#ifdef NEED_REENTRANT
/* Solaris machines needs _REENTRANT set for a few function prototypes and
@ -72,14 +98,14 @@ typedef unsigned char bool;
#define _REENTRANT
#endif
#include <stdio.h>
#ifndef OS
#ifdef WIN32
#define OS "win32"
#else
#define OS "unknown"
#ifdef HAVE_ASSERT_H
#include <assert.h>
#endif
#include <errno.h>
#ifdef __TANDEM /* for nsr-tandem-nsk systems */
#include <floss.h>
#endif
#if defined(HAVE_X509_H) && defined(HAVE_SSL_H) && defined(HAVE_RSA_H) && \
@ -100,18 +126,26 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
#ifdef VMS
#include "../include/curl/stdcheaders.h"
#else
#include <curl/stdcheaders.h>
#endif
#if defined(CURLDEBUG) && defined(HAVE_ASSERT_H)
#define curlassert(x) assert(x)
#else
#ifdef _AIX
#include <curl/stdcheaders.h>
/* does nothing without CURLDEBUG defined */
#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 */
#else
#define SEND_4TH_ARG 0
#endif
/* Below we define four functions. They should
1. close a socket
2. read from a socket
@ -122,71 +156,139 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
*/
#ifdef WIN32
/* Disable unnecessary warnings on Visual Studio */
#ifdef _MSC_VER
#pragma warning ( disable : 4127 )
#pragma warning ( disable : 4514 )
#pragma warning ( disable : 4706 )
#pragma warning ( disable : 4131 ) /* Old style declaration */
#pragma warning ( disable : 4055 ) /* Cast void*(*)() to void* */
#pragma warning ( disable : 4311 ) /* Allow cast from void* to long/int */
#pragma warning ( disable : 4312 ) /* Allow cast from long to char* */
struct _RPC_ASYNC_STATE;
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN /* Prevent including <winsock*.h> in <windows.h> */
#endif
/* Disable unnecessary warnings on Borland */
#ifdef __BORLANDC__
#pragma warn -8004
#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__)
#define sclose(x) closesocket(x)
#define sread(x,y,z) recv(x,y,z,0)
#define swrite(x,y,z) (size_t)send(x,y,z,0)
#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,0)
#define swrite(x,y,z) send(x,y,z,0)
#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
#define PATH_CHAR ";"
#define DIR_CHAR "\\"
#define DOT_CHAR "_"
#else
#ifdef DJGPP
#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
#include <tcp.h>
#ifdef word
#undef word
#endif
#else
#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
#define sclose(x) close(x)
#define sread(x,y,z) recv(x,y,z,0)
#define swrite(x,y,z) send(x,y,z,0)
#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
#define HAVE_ALARM
#define PATH_CHAR ":"
#endif
#ifdef _AMIGASF
#undef HAVE_ALARM
#undef sclose
#define sclose(x) CloseSocket(x)
#endif
#define DIR_CHAR "/"
#define DOT_CHAR "."
#ifdef HAVE_STRCASECMP
/* this is for "-ansi -Wall -pedantic" to stop complaining! */
extern int (strcasecmp)(const char *s1, const char *s2);
extern int (strncasecmp)(const char *s1, const char *s2, size_t n);
#ifdef DJGPP
#undef DOT_CHAR
#define DOT_CHAR "_"
#endif
#ifndef fileno /* sunos 4 have this as a macro! */
int fileno( FILE *stream);
#endif
#endif
#endif
/*
* Curl_addrinfo MUST be used for name resolving information.
* Information regarding a single IP witin a Curl_addrinfo MUST be stored in
* a Curl_ipconnect struct.
*/
#ifdef ENABLE_IPV6
typedef struct addrinfo Curl_addrinfo;
typedef struct addrinfo Curl_ipconnect;
/* now typedef our socket type */
#ifdef WIN32
typedef SOCKET curl_socket_t;
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
typedef struct hostent Curl_addrinfo;
typedef struct in_addr Curl_ipconnect;
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
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(USE_ARES) && \
!defined(__LCC__) /* lcc-win32 doesn't have _beginthreadex() */
#ifdef ENABLE_IPV6
#define USE_THREADING_GETADDRINFO
#else
#define USE_THREADING_GETHOSTBYNAME /* Cygwin uses alarm() function */
#endif
#endif
#ifdef mpeix
#define IOCTL_3_ARGS
#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
#endif
#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. */
#define USE_LIBIDN
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#endif
#endif /* __CONFIG_H */

219
Source/CTest/Curl/share.c Normal file
View File

@ -0,0 +1,219 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "urldata.h"
#include "share.h"
#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
CURLSH *
curl_share_init(void)
{
struct Curl_share *share =
(struct Curl_share *)malloc(sizeof(struct Curl_share));
if (share) {
memset (share, 0, sizeof(struct Curl_share));
share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
}
return share;
}
CURLSHcode
curl_share_setopt(CURLSH *sh, CURLSHoption option, ...)
{
struct Curl_share *share = (struct Curl_share *)sh;
va_list param;
int type;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
void *ptr;
if (share->dirty)
/* don't allow setting options while one or more handles are already
using this share */
return CURLSHE_IN_USE;
va_start(param, option);
switch(option) {
case CURLSHOPT_SHARE:
/* this is a type this share will share */
type = va_arg(param, int);
share->specifier |= (1<<type);
switch( type ) {
case CURL_LOCK_DATA_DNS:
if (!share->hostcache) {
share->hostcache = Curl_mk_dnscache();
if(!share->hostcache)
return CURLSHE_NOMEM;
}
break;
#ifndef CURL_DISABLE_HTTP
case CURL_LOCK_DATA_COOKIE:
if (!share->cookies) {
share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE );
if(!share->cookies)
return CURLSHE_NOMEM;
}
break;
#endif /* CURL_DISABLE_HTTP */
case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */
case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
default:
return CURLSHE_BAD_OPTION;
}
break;
case CURLSHOPT_UNSHARE:
/* this is a type this share will no longer share */
type = va_arg(param, int);
share->specifier &= ~(1<<type);
switch( type )
{
case CURL_LOCK_DATA_DNS:
if (share->hostcache) {
Curl_hash_destroy(share->hostcache);
share->hostcache = NULL;
}
break;
#ifndef CURL_DISABLE_HTTP
case CURL_LOCK_DATA_COOKIE:
if (share->cookies) {
Curl_cookie_cleanup(share->cookies);
share->cookies = NULL;
}
break;
#endif /* CURL_DISABLE_HTTP */
case CURL_LOCK_DATA_SSL_SESSION:
break;
case CURL_LOCK_DATA_CONNECT:
break;
default:
return CURLSHE_BAD_OPTION;
}
break;
case CURLSHOPT_LOCKFUNC:
lockfunc = va_arg(param, curl_lock_function);
share->lockfunc = lockfunc;
break;
case CURLSHOPT_UNLOCKFUNC:
unlockfunc = va_arg(param, curl_unlock_function);
share->unlockfunc = unlockfunc;
break;
case CURLSHOPT_USERDATA:
ptr = va_arg(param, void *);
share->clientdata = ptr;
break;
default:
return CURLSHE_BAD_OPTION;
}
return CURLSHE_OK;
}
CURLSHcode
curl_share_cleanup(CURLSH *sh)
{
struct Curl_share *share = (struct Curl_share *)sh;
if (share == NULL)
return CURLSHE_INVALID;
if(share->lockfunc)
share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
share->clientdata);
if (share->dirty) {
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
return CURLSHE_IN_USE;
}
if(share->hostcache)
Curl_hash_destroy(share->hostcache);
#ifndef CURL_DISABLE_HTTP
if(share->cookies)
Curl_cookie_cleanup(share->cookies);
#endif /* CURL_DISABLE_HTTP */
if(share->unlockfunc)
share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
free(share);
return CURLSHE_OK;
}
CURLSHcode
Curl_share_lock(struct SessionHandle *data, curl_lock_data type,
curl_lock_access accesstype)
{
struct Curl_share *share = data->share;
if (share == NULL)
return CURLSHE_INVALID;
if(share->specifier & (1<<type)) {
if(share->lockfunc) /* only call this if set! */
share->lockfunc(data, type, accesstype, share->clientdata);
}
/* else if we don't share this, pretend successful lock */
return CURLSHE_OK;
}
CURLSHcode
Curl_share_unlock(struct SessionHandle *data, curl_lock_data type)
{
struct Curl_share *share = data->share;
if (share == NULL)
return CURLSHE_INVALID;
if(share->specifier & (1<<type)) {
if(share->unlockfunc) /* only call this if set! */
share->unlockfunc (data, type, share->clientdata);
}
return CURLSHE_OK;
}

View File

@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -26,27 +26,30 @@
#include "setup.h"
#include <curl/curl.h>
#include "cookie.h"
/* this struct is libcurl-private, don't export details */
struct Curl_share {
unsigned int specifier;
unsigned int locked;
unsigned int dirty;
volatile unsigned int dirty;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
void *clientdata;
curl_hash *hostcache;
struct CookieInfo *cookies;
};
CURLSHcode Curl_share_aquire_lock (struct SessionHandle *, curl_lock_data);
CURLSHcode Curl_share_release_lock (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 */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -25,9 +25,6 @@
#include <stdio.h>
#include <string.h>
#if defined(__MINGW32__)
#include <winsock.h>
#endif
#include <curl/curl.h>
#include "urldata.h"
@ -68,11 +65,3 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
}
return CURLE_OK;
}
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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
@ -23,7 +23,7 @@
* $Id$
***************************************************************************/
#include "urldata.h"
CURLcode Curl_SSLConnect(struct connectdata *conn);
CURLcode Curl_SSLConnect(struct connectdata *conn, int sockindex);
void Curl_SSL_init(void); /* Global SSL init */
void Curl_SSL_cleanup(void); /* Global SSL cleanup */

View File

@ -1,16 +1,16 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -26,14 +26,22 @@
#include <string.h>
#include <ctype.h>
#include "strequal.h"
#ifdef HAVE_STRCASECMP
/* this is for "-ansi -Wall -pedantic" to stop complaining! */
extern int (strcasecmp)(const char *s1, const char *s2);
extern int (strncasecmp)(const char *s1, const char *s2, size_t n);
#endif
int curl_strequal(const char *first, const char *second)
{
#if defined(HAVE_STRCASECMP)
return !(strcasecmp)(first, second);
#elif defined(HAVE_STRICMP)
return !(stricmp)(first, second);
#elif defined(HAVE_STRCMPI)
return !(strcmpi)(first, second);
#elif defined(HAVE_STRICMP)
return !(stricmp)(first, second);
#else
while (*first && *second) {
if (toupper(*first) != toupper(*second)) {
@ -50,10 +58,10 @@ int curl_strnequal(const char *first, const char *second, size_t max)
{
#if defined(HAVE_STRCASECMP)
return !strncasecmp(first, second, max);
#elif defined(HAVE_STRICMP)
return !strnicmp(first, second, max);
#elif defined(HAVE_STRCMPI)
return !strncmpi(first, second, max);
#elif defined(HAVE_STRICMP)
return !strnicmp(first, second, max);
#else
while (*first && *second && max) {
if (toupper(*first) != toupper(*second)) {
@ -70,6 +78,25 @@ int curl_strnequal(const char *first, const char *second, size_t max)
#endif
}
/*
* Curl_strcasestr() finds the first occurrence of the substring needle in the
* string haystack. The terminating `\0' characters are not compared. The
* matching is done CASE INSENSITIVE, which thus is the difference between
* this and strstr().
*/
char *Curl_strcasestr(const char *haystack, const char *needle)
{
size_t nlen = strlen(needle);
size_t hlen = strlen(haystack);
while(hlen-- >= nlen) {
if(curl_strnequal(haystack, needle, nlen))
return (char *)haystack;
haystack++;
}
return NULL;
}
#ifndef HAVE_STRLCAT
/*
* The strlcat() function appends the NUL-terminated string src to the end
@ -82,7 +109,7 @@ int curl_strnequal(const char *first, const char *second, size_t max)
* src. While this may seem somewhat confusing it was done to make trunca-
* tion detection simple.
*
*
*
*/
size_t Curl_strlcat(char *dst, const char *src, size_t siz)
{
@ -111,11 +138,3 @@ size_t Curl_strlcat(char *dst, const char *src, size_t siz)
return(dlen + (s - src)); /* count does not include NUL */
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -1,18 +1,18 @@
#ifndef __STREQUAL_H
#define __STREQUAL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* 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.
@ -36,6 +36,9 @@ int curl_strnequal(const char *first, const char *second, size_t max);
argument is zero-byte terminated */
#define checkprefix(a,b) strnequal(a,b,strlen(a))
/* case insensitive strstr() */
char *Curl_strcasestr(const char *haystack, const char *needle);
#ifndef HAVE_STRLCAT
#define strlcat(x,y,z) Curl_strlcat(x,y,z)
size_t Curl_strlcat(char *dst, const char *src, size_t siz);

View File

@ -0,0 +1,558 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 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.
*
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "strerror.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#ifdef HAVE_NO_STRERROR_R_DECL
#ifdef HAVE_POSIX_STRERROR_R
/* seen on AIX 5100-02 gcc 2.9 */
extern int strerror_r(int errnum, char *strerrbuf, size_t buflen);
#else
extern char *strerror_r(int errnum, char *buf, size_t buflen);
#endif
#endif
const char *
curl_easy_strerror(CURLcode error)
{
switch (error) {
case CURLE_OK:
return "no error";
case CURLE_UNSUPPORTED_PROTOCOL:
return "unsupported protocol";
case CURLE_FAILED_INIT:
return "failed init";
case CURLE_URL_MALFORMAT:
return "URL using bad/illegal format or missing URL";
case CURLE_COULDNT_RESOLVE_PROXY:
return "couldnt resolve proxy";
case CURLE_COULDNT_RESOLVE_HOST:
return "couldnt resolve host";
case CURLE_COULDNT_CONNECT:
return "couldn't connect";
case CURLE_FTP_WEIRD_SERVER_REPLY:
return "FTP: weird server reply";
case CURLE_FTP_ACCESS_DENIED:
return "FTP: access denied";
case CURLE_FTP_USER_PASSWORD_INCORRECT:
return "FTP: user and/or password incorrect";
case CURLE_FTP_WEIRD_PASS_REPLY:
return "FTP: unknown PASS reply";
case CURLE_FTP_WEIRD_USER_REPLY:
return "FTP: unknown USER reply";
case CURLE_FTP_WEIRD_PASV_REPLY:
return "FTP: unknown PASV reply";
case CURLE_FTP_WEIRD_227_FORMAT:
return "FTP: unknown 227 response format";
case CURLE_FTP_CANT_GET_HOST:
return "FTP: can't figure out the host in the PASV response";
case CURLE_FTP_CANT_RECONNECT:
return "FTP: can't connect to server the response code is unknown";
case CURLE_FTP_COULDNT_SET_BINARY:
return "FTP: couldn't set binary mode";
case CURLE_PARTIAL_FILE:
return "Transferred a partial file";
case CURLE_FTP_COULDNT_RETR_FILE:
return "FTP: couldn't retrieve (RETR failed) the specified file";
case CURLE_FTP_WRITE_ERROR:
return "FTP: the post-transfer acknowledge response was not OK";
case CURLE_FTP_QUOTE_ERROR:
return "FTP: a quote command returned error";
case CURLE_HTTP_RETURNED_ERROR:
return "HTTP response code said error";
case CURLE_WRITE_ERROR:
return "failed writing received data to disk/application";
case CURLE_FTP_COULDNT_STOR_FILE:
return "failed FTP upload (the STOR command)";
case CURLE_READ_ERROR:
return "failed to open/read local data from file/application";
case CURLE_OUT_OF_MEMORY:
return "out of memory";
case CURLE_OPERATION_TIMEOUTED:
return "a timeout was reached";
case CURLE_FTP_COULDNT_SET_ASCII:
return "FTP could not set ASCII mode (TYPE A)";
case CURLE_FTP_PORT_FAILED:
return "FTP command PORT failed";
case CURLE_FTP_COULDNT_USE_REST:
return "FTP command REST failed";
case CURLE_FTP_COULDNT_GET_SIZE:
return "FTP command SIZE failed";
case CURLE_HTTP_RANGE_ERROR:
return "a range was requested but the server did not deliver it";
case CURLE_HTTP_POST_ERROR:
return "internal problem setting up the POST";
case CURLE_SSL_CONNECT_ERROR:
return "SSL connect error";
case CURLE_FTP_BAD_DOWNLOAD_RESUME:
return "couldn't resume FTP download";
case CURLE_FILE_COULDNT_READ_FILE:
return "couldn't read a file:// file";
case CURLE_LDAP_CANNOT_BIND:
return "LDAP: cannot bind";
case CURLE_LDAP_SEARCH_FAILED:
return "LDAP: search failed";
case CURLE_LIBRARY_NOT_FOUND:
return "a required shared library was not found";
case CURLE_FUNCTION_NOT_FOUND:
return "a required function in the shared library was not found";
case CURLE_ABORTED_BY_CALLBACK:
return "the operation was aborted by an application callback";
case CURLE_BAD_FUNCTION_ARGUMENT:
return "a libcurl function was given a bad argument";
case CURLE_INTERFACE_FAILED:
return "failed binding local connection end";
case CURLE_TOO_MANY_REDIRECTS :
return "number of redirects hit maximum amount";
case CURLE_UNKNOWN_TELNET_OPTION:
return "User specified an unknown option";
case CURLE_TELNET_OPTION_SYNTAX :
return "Malformed telnet option";
case CURLE_SSL_PEER_CERTIFICATE:
return "SSL peer certificate was not ok";
case CURLE_GOT_NOTHING:
return "server returned nothing (no headers, no data)";
case CURLE_SSL_ENGINE_NOTFOUND:
return "SSL crypto engine not found";
case CURLE_SSL_ENGINE_SETFAILED:
return "can not set SSL crypto engine as default";
case CURLE_SEND_ERROR:
return "failed sending data to the peer";
case CURLE_RECV_ERROR:
return "failure when receiving data from the peer";
case CURLE_SHARE_IN_USE:
return "share is already in use";
case CURLE_SSL_CERTPROBLEM:
return "problem with the local SSL certificate";
case CURLE_SSL_CIPHER:
return "couldn't use specified SSL cipher";
case CURLE_SSL_CACERT:
return "problem with the SSL CA cert (path? access rights?)";
case CURLE_BAD_CONTENT_ENCODING:
return "Unrecognized HTTP Content-Encoding";
case CURLE_LDAP_INVALID_URL:
return "Invalid LDAP URL";
case CURLE_FILESIZE_EXCEEDED:
return "Maximum file size exceeded";
case CURLE_FTP_SSL_FAILED:
return "Requested FTP SSL level failed";
case CURLE_URL_MALFORMAT_USER: /* not used by current libcurl */
case CURLE_MALFORMAT_USER: /* not used by current libcurl */
case CURLE_BAD_CALLING_ORDER: /* not used by current libcurl */
case CURLE_BAD_PASSWORD_ENTERED:/* not used by current libcurl */
case CURLE_OBSOLETE: /* not used by current libcurl */
case CURL_LAST:
break;
}
/*
* By using a switch, gcc -Wall will complain about enum values
* which do not appear, helping keep this function up-to-date.
* By using gcc -Wall -Werror, you can't forget.
*
* A table would not have the same benefit. Most compilers will
* generate code very similar to a table in any case, so there
* is little performance gain from a table. And something is broken
* for the user's application, anyways, so does it matter how fast
* it _doesn't_ work?
*
* The line number for the error will be near this comment, which
* is why it is here, and not at the start of the switch.
*/
return "unknown error";
}
const char *
curl_multi_strerror(CURLMcode error)
{
switch (error) {
case CURLM_CALL_MULTI_PERFORM:
return "please call curl_multi_perform() soon";
case CURLM_OK:
return "no error";
case CURLM_BAD_HANDLE:
return "invalid multi handle";
case CURLM_BAD_EASY_HANDLE:
return "invalid easy handle";
case CURLM_OUT_OF_MEMORY:
return "out of memory";
case CURLM_INTERNAL_ERROR:
return "internal error";
case CURLM_LAST:
break;
}
return "unknown error";
}
const char *
curl_share_strerror(CURLSHcode error)
{
switch (error) {
case CURLSHE_OK:
return "no error";
case CURLSHE_BAD_OPTION:
return "unknown share option";
case CURLSHE_IN_USE:
return "share currently in use";
case CURLSHE_INVALID:
return "invalid share handle";
case CURLSHE_NOMEM:
return "out of memory";
case CURLSHE_LAST:
break;
}
return "CURLSH unknown";
}
#if defined(WIN32) && !defined(__CYGWIN__)
/* This function handles most / all (?) Winsock errors cURL is able to produce.
*/
static const char *
get_winsock_error (int err, char *buf, size_t len)
{
char *p;
switch (err) {
case WSAEINTR:
p = "Call interrupted.";
break;
case WSAEBADF:
p = "Bad file";
break;
case WSAEACCES:
p = "Bad access";
break;
case WSAEFAULT:
p = "Bad argument";
break;
case WSAEINVAL:
p = "Invalid arguments";
break;
case WSAEMFILE:
p = "Out of file descriptors";
break;
case WSAEWOULDBLOCK:
p = "Call would block";
break;
case WSAEINPROGRESS:
case WSAEALREADY:
p = "Blocking call in progress";
break;
case WSAENOTSOCK:
p = "Descriptor is not a socket.";
break;
case WSAEDESTADDRREQ:
p = "Need destination address";
break;
case WSAEMSGSIZE:
p = "Bad message size";
break;
case WSAEPROTOTYPE:
p = "Bad protocol";
break;
case WSAENOPROTOOPT:
p = "Protocol option is unsupported";
break;
case WSAEPROTONOSUPPORT:
p = "Protocol is unsupported";
break;
case WSAESOCKTNOSUPPORT:
p = "Socket is unsupported";
break;
case WSAEOPNOTSUPP:
p = "Operation not supported";
break;
case WSAEAFNOSUPPORT:
p = "Address family not supported";
break;
case WSAEPFNOSUPPORT:
p = "Protocol family not supported";
break;
case WSAEADDRINUSE:
p = "Address already in use";
break;
case WSAEADDRNOTAVAIL:
p = "Address not available";
break;
case WSAENETDOWN:
p = "Network down";
break;
case WSAENETUNREACH:
p = "Network unreachable";
break;
case WSAENETRESET:
p = "Network has been reset";
break;
case WSAECONNABORTED:
p = "Connection was aborted";
break;
case WSAECONNRESET:
p = "Connection was reset";
break;
case WSAENOBUFS:
p = "No buffer space";
break;
case WSAEISCONN:
p = "Socket is already connected";
break;
case WSAENOTCONN:
p = "Socket is not connected";
break;
case WSAESHUTDOWN:
p = "Socket has been shut down";
break;
case WSAETOOMANYREFS:
p = "Too many references";
break;
case WSAETIMEDOUT:
p = "Timed out";
break;
case WSAECONNREFUSED:
p = "Connection refused";
break;
case WSAELOOP:
p = "Loop??";
break;
case WSAENAMETOOLONG:
p = "Name too long";
break;
case WSAEHOSTDOWN:
p = "Host down";
break;
case WSAEHOSTUNREACH:
p = "Host unreachable";
break;
case WSAENOTEMPTY:
p = "Not empty";
break;
case WSAEPROCLIM:
p = "Process limit reached";
break;
case WSAEUSERS:
p = "Too many users";
break;
case WSAEDQUOT:
p = "Bad quota";
break;
case WSAESTALE:
p = "Something is stale";
break;
case WSAEREMOTE:
p = "Remote error";
break;
case WSAEDISCON:
p = "Disconnected";
break;
/* Extended Winsock errors */
case WSASYSNOTREADY:
p = "Winsock library is not ready";
break;
case WSANOTINITIALISED:
p = "Winsock library not initalised";
break;
case WSAVERNOTSUPPORTED:
p = "Winsock version not supported.";
break;
/* getXbyY() errors (already handled in herrmsg):
* Authoritative Answer: Host not found */
case WSAHOST_NOT_FOUND:
p = "Host not found";
break;
/* Non-Authoritative: Host not found, or SERVERFAIL */
case WSATRY_AGAIN:
p = "Host not found, try again";
break;
/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
case WSANO_RECOVERY:
p = "Unrecoverable error in call to nameserver";
break;
/* Valid name, no data record of requested type */
case WSANO_DATA:
p = "No data record of requested type";
break;
default:
return NULL;
}
strncpy (buf, p, len);
buf [len-1] = '\0';
return buf;
}
#endif /* WIN32 && !__CYGWIN__ */
/*
* Our thread-safe and smart strerror() replacement.
*
* The 'err' argument passed in to this function MUST be a true errno number
* as reported on this system. We do no range checking on the number before
* we pass it to the "number-to-message" convertion function and there might
* be systems that don't do proper range checking in there themselves.
*
* We don't do range checking (on systems other than Windows) since there is
* no good reliable and portable way to do it.
*/
const char *Curl_strerror(struct connectdata *conn, int err)
{
char *buf, *p;
size_t max;
curlassert(conn);
curlassert(err >= 0);
buf = conn->syserr_buf;
max = sizeof(conn->syserr_buf)-1;
*buf = '\0';
#if defined(WIN32) && !defined(__CYGWIN__)
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if (err >= 0 && err < sys_nerr)
strncpy(buf, strerror(err), max);
else {
if (!get_winsock_error (err, buf, max) &&
!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
LANG_NEUTRAL, buf, max, NULL))
snprintf(buf, max, "Unknown error %d (%#x)", err, err);
}
#else /* not native Windows coming up */
/* These should be atomic and hopefully thread-safe */
#ifdef HAVE_STRERROR_R
/* There are two different APIs for strerror_r(). The POSIX and the GLIBC
versions. */
#ifdef HAVE_POSIX_STRERROR_R
strerror_r(err, buf, max);
/* this may set errno to ERANGE if insufficient storage was supplied via
'strerrbuf' and 'buflen' to contain the generated message string, or
EINVAL if the value of 'errnum' is not a valid error number.*/
#else
{
/* HAVE_GLIBC_STRERROR_R */
char buffer[256];
char *msg = strerror_r(err, buffer, sizeof(buffer));
/* this version of strerror_r() only *might* use the buffer we pass to
the function, but it always returns the error message as a pointer,
so we must copy that string unconditionally */
strncpy(buf, msg, max);
}
#endif /* end of HAVE_GLIBC_STRERROR_R */
#else /* HAVE_STRERROR_R */
strncpy(buf, strerror(err), max);
#endif /* end of HAVE_STRERROR_R */
#endif /* end of ! Windows */
buf[max] = '\0'; /* make sure the string is zero terminated */
/* strip trailing '\r\n' or '\n'. */
if ((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2)
*p = '\0';
if ((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
*p = '\0';
return buf;
}

View File

@ -0,0 +1,30 @@
#ifndef __CURL_STRERROR_H
#define __CURL_STRERROR_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "urldata.h"
const char *Curl_strerror (struct connectdata *conn, int err);
#endif

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