mirror of
https://github.com/reactos/CMake.git
synced 2025-02-12 14:58:45 +00:00
ENH: Update Curl to 7.12.1
This commit is contained in:
parent
50da032847
commit
609801fe67
@ -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)
|
@ -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)
|
||||
|
49
Source/CTest/Curl/amigaos.c
Normal file
49
Source/CTest/Curl/amigaos.c
Normal 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;
|
||||
}
|
52
Source/CTest/Curl/amigaos.h
Normal file
52
Source/CTest/Curl/amigaos.h
Normal 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 */
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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*/
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 *);
|
||||
|
@ -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
55
Source/CTest/Curl/curl/curlver.h
Normal file
55
Source/CTest/Curl/curl/curlver.h
Normal 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 */
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 *);
|
||||
|
@ -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
95
Source/CTest/Curl/curlx.h
Normal 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 */
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
@ -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
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
301
Source/CTest/Curl/hostares.c
Normal file
301
Source/CTest/Curl/hostares.c
Normal 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 */
|
170
Source/CTest/Curl/hostasyn.c
Normal file
170
Source/CTest/Curl/hostasyn.c
Normal 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
@ -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
449
Source/CTest/Curl/hostip4.c
Normal 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
263
Source/CTest/Curl/hostip6.c
Normal 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
149
Source/CTest/Curl/hostsyn.c
Normal 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 */
|
550
Source/CTest/Curl/hostthre.c
Normal file
550
Source/CTest/Curl/hostthre.c
Normal 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
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
482
Source/CTest/Curl/http_digest.c
Normal file
482
Source/CTest/Curl/http_digest.c
Normal 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
|
53
Source/CTest/Curl/http_digest.h
Normal file
53
Source/CTest/Curl/http_digest.h
Normal 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
|
332
Source/CTest/Curl/http_negotiate.c
Normal file
332
Source/CTest/Curl/http_negotiate.c
Normal 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
|
39
Source/CTest/Curl/http_negotiate.h
Normal file
39
Source/CTest/Curl/http_negotiate.h
Normal 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
|
585
Source/CTest/Curl/http_ntlm.c
Normal file
585
Source/CTest/Curl/http_ntlm.c
Normal 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 */
|
143
Source/CTest/Curl/http_ntlm.h
Normal file
143
Source/CTest/Curl/http_ntlm.h
Normal 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
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
198
Source/CTest/Curl/inet_ntop.c
Normal file
198
Source/CTest/Curl/inet_ntop.c
Normal 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 */
|
37
Source/CTest/Curl/inet_ntop.h
Normal file
37
Source/CTest/Curl/inet_ntop.h
Normal 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 */
|
240
Source/CTest/Curl/inet_pton.c
Normal file
240
Source/CTest/Curl/inet_pton.c
Normal 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 */
|
@ -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 */
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
348
Source/CTest/Curl/md5.c
Normal 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
29
Source/CTest/Curl/md5.h
Normal 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
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
50
Source/CTest/Curl/memory.h
Normal file
50
Source/CTest/Curl/memory.h
Normal 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 */
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
300
Source/CTest/Curl/nwlib.c
Normal 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
219
Source/CTest/Curl/share.c
Normal 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;
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
@ -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 */
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
558
Source/CTest/Curl/strerror.c
Normal file
558
Source/CTest/Curl/strerror.c
Normal 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;
|
||||
}
|
30
Source/CTest/Curl/strerror.h
Normal file
30
Source/CTest/Curl/strerror.h
Normal 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
Loading…
x
Reference in New Issue
Block a user