r898 - in trunk: . code code/client code/libcurl code/libcurl/curl code/libs code/libs/win32 code/qcommon code/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Sep 11 12:41:56 EDT 2006


Author: tjw
Date: 2006-09-11 12:41:55 -0400 (Mon, 11 Sep 2006)
New Revision: 898

Added:
   trunk/code/client/cl_curl.c
   trunk/code/client/cl_curl.h
   trunk/code/libcurl/
   trunk/code/libcurl/curl/
   trunk/code/libcurl/curl/curl.h
   trunk/code/libcurl/curl/curlver.h
   trunk/code/libcurl/curl/easy.h
   trunk/code/libcurl/curl/mprintf.h
   trunk/code/libcurl/curl/multi.h
   trunk/code/libcurl/curl/stdcheaders.h
   trunk/code/libcurl/curl/types.h
   trunk/code/libs/win32/
   trunk/code/libs/win32/libcurl.a
Modified:
   trunk/Makefile
   trunk/README
   trunk/code/client/cl_main.c
   trunk/code/client/cl_parse.c
   trunk/code/client/client.h
   trunk/code/qcommon/qcommon.h
   trunk/code/server/sv_client.c
   trunk/code/server/sv_init.c
Log:
* add cURL support for HTTP/FTP downloading (bug 2661)


Modified: trunk/Makefile
===================================================================
--- trunk/Makefile	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/Makefile	2006-09-11 16:41:55 UTC (rev 898)
@@ -100,6 +100,18 @@
 USE_OPENAL_DLOPEN=0
 endif
 
+ifndef USE_CURL
+USE_CURL=1
+endif
+
+ifndef USE_CURL_DLOPEN
+  ifeq ($(PLATFORM),mingw32)
+    USE_CURL_DLOPEN=0
+  else
+    USE_CURL_DLOPEN=1
+  endif
+endif
+
 ifndef USE_CODEC_VORBIS
 USE_CODEC_VORBIS=0
 endif
@@ -187,6 +199,13 @@
       BASE_CFLAGS += -DUSE_OPENAL_DLOPEN=1
     endif
   endif
+  
+  ifeq ($(USE_CURL),1)
+    BASE_CFLAGS += -DUSE_CURL=1
+    ifeq ($(USE_CURL_DLOPEN),1)
+      BASE_CFLAGS += -DUSE_CURL_DLOPEN=1
+    endif
+  endif
 
   ifeq ($(USE_CODEC_VORBIS),1)
     BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
@@ -249,6 +268,12 @@
       CLIENT_LDFLAGS += -lopenal
     endif
   endif
+  
+  ifeq ($(USE_CURL),1)
+    ifneq ($(USE_CURL_DLOPEN),1)
+      CLIENT_LDFLAGS += -lcurl
+    endif
+  endif
 
   ifeq ($(USE_CODEC_VORBIS),1)
     CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
@@ -348,6 +373,15 @@
       BASE_CFLAGS += -DUSE_OPENAL_DLOPEN=1
     endif
   endif
+  
+  ifeq ($(USE_CURL),1)
+    BASE_CFLAGS += -DUSE_CURL=1
+    ifneq ($(USE_CURL_DLOPEN),1)
+      CLIENT_LDFLAGS += -lcurl
+    else
+      BASE_CFLAGS += -DUSE_CURL_DLOPEN=1
+    endif
+  endif
 
   ifeq ($(USE_CODEC_VORBIS),1)
     BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
@@ -404,6 +438,13 @@
   ifeq ($(USE_OPENAL),1)
     BASE_CFLAGS += -DUSE_OPENAL=1 -DUSE_OPENAL_DLOPEN=1
   endif
+  
+  ifeq ($(USE_CURL),1)
+    BASE_CFLAGS += -DUSE_CURL=1
+    ifneq ($(USE_CURL_DLOPEN),1)
+      BASE_CFLAGS += -DCURL_STATICLIB
+    endif
+  endif
 
   ifeq ($(USE_CODEC_VORBIS),1)
     BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
@@ -430,6 +471,12 @@
   LDFLAGS= -mwindows -lshfolder -lwsock32 -lgdi32 -lwinmm -lole32
   CLIENT_LDFLAGS=
 
+  ifeq ($(USE_CURL),1)
+    ifneq ($(USE_CURL_DLOPEN),1)
+      CLIENT_LDFLAGS += $(LIBSDIR)/win32/libcurl.a
+    endif
+  endif
+
   ifeq ($(USE_CODEC_VORBIS),1)
     CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
   endif
@@ -847,6 +894,8 @@
   $(B)/client/qal.o \
   $(B)/client/snd_openal.o \
   \
+  $(B)/client/cl_curl.o \
+  \
   $(B)/client/sv_bot.o \
   $(B)/client/sv_ccmds.o \
   $(B)/client/sv_client.o \
@@ -1067,6 +1116,8 @@
 $(B)/client/qal.o : $(CDIR)/qal.c; $(DO_CC)
 $(B)/client/snd_openal.o : $(CDIR)/snd_openal.c; $(DO_CC)
 
+$(B)/client/cl_curl.o : $(CDIR)/cl_curl.c; $(DO_CC)
+
 $(B)/client/sv_bot.o : $(SDIR)/sv_bot.c; $(DO_CC)
 $(B)/client/sv_client.o : $(SDIR)/sv_client.c; $(DO_CC)
 $(B)/client/sv_ccmds.o : $(SDIR)/sv_ccmds.c; $(DO_CC)

Modified: trunk/README
===================================================================
--- trunk/README	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/README	2006-09-11 16:41:55 UTC (rev 898)
@@ -23,6 +23,7 @@
   * Much improved QVM tools
   * Support for various esoteric operating systems (see
     http://icculus.org/quake3/?page=status)
+  * HTTP/FTP download redirection (using cURL)
   * Many, many bug fixes
 
 The map editor and associated compiling tools are not included. We suggest you
@@ -140,6 +141,9 @@
   cl_platformSensitivity            - read only, indicates the mouse input
                                       scaling
   r_ext_texture_filter_anisotropic  - anisotropic texture filtering
+  cl_cURLLib                        - filename of cURL library to load
+  sv_dlURL                          - the base of the HTTP or FTP site that
+                                      holds custom pk3 files for your server 
 
 New commands
   video [filename]        - start video capture (use with demo command)
@@ -192,7 +196,44 @@
   compiler. See http://www.quakesrc.org/forums/viewtopic.php?t=5665 (if it
   still exists when you read this) for more details.
 
+Using HTTP/FTP Download Support (Server)
+    You can enable redirected downloads on your server even if it's not
+    an ioquake3 server.  You simply need to use the 'sets' command to put
+    the sv_dlURL cvar into your SERVERINFO string and ensure sv_allowDownloads
+    is set to 1
 
+    sv_dlURL is the base of the URL that contains your custom .pk3 files
+    the client will append both fs_game and the filename to the end of
+    this value.  For example, if you have sv_dlURL set to
+    "http://icculus.org/quake3", fs_game is "baseq3", and the client is
+    missing "test.pk3", it will attempt to download from the URL
+    "http://icculus.org/quake3/baseq3/test.pk3"
+
+    sv_allowDownload's value is now a bitmask made up of the following
+    flags:
+      1 - ENABLE
+      2 - do not use HTTP/FTP downloads
+      4 - do not use UDP downloads
+      8 - do not ask the client to disconnect when using HTTP/FTP
+
+    Server operators who are concerned about potential "leeching" from their
+    HTTP servers from other ioquake3 servers can make use of the HTTP_REFERER
+    that ioquake3 sets which is "ioQ3://{SERVER_IP}:{SERVER_PORT}".  For,
+    example, Apache's mod_rewrite can restrict access based on HTTP_REFERER. 
+
+Using HTTP/FTP Download Support (Client)
+    Simply setting cl_allowDownload to 1 will enable HTTP/FTP downloads
+    assuming ioquake3 was compiled with USE_CURL=1 (the default).
+    like sv_allowDownload, cl_allowDownload also uses a bitmask value
+    supporting the following flags:
+      1 - ENABLE
+      2 - do not use HTTP/FTP downloads
+      4 - do not use UDP downloads
+
+    When ioquake3 is built with USE_CURL_DLOPEN=1 (default on some platforms),
+    it will use the value of the cvar cl_cURLLib as the filename of the cURL
+    library to dynamically load. 
+
 ------------------------------------------------------------- Contributing -----
 
 Please send all patches to bugzilla (https://bugzilla.icculus.org), or join the

Added: trunk/code/client/cl_curl.c
===================================================================
--- trunk/code/client/cl_curl.c	                        (rev 0)
+++ trunk/code/client/cl_curl.c	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,358 @@
+/*
+===========================================================================
+Copyright (C) 2006 Tony J. White (tjw at tjw.org)
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+#if USE_CURL
+#include "client.h"
+cvar_t *cl_cURLLib;
+
+#if USE_CURL_DLOPEN
+
+#if USE_SDL_VIDEO
+#include "SDL.h"
+#include "SDL_loadso.h"
+#define OBJTYPE void *
+#define OBJLOAD(x) SDL_LoadObject(x)
+#define SYMLOAD(x,y) SDL_LoadFunction(x,y)
+#define OBJFREE(x) SDL_UnloadObject(x)
+
+#elif defined _WIN32
+#include <windows.h>
+#define OBJTYPE HMODULE
+#define OBJLOAD(x) LoadLibrary(x)
+#define SYMLOAD(x,y) GetProcAddress(x,y)
+#define OBJFREE(x) FreeLibrary(x)
+
+#elif defined __linux__ || defined __FreeBSD__ || defined MACOS_X || defined __sun
+#include <dlfcn.h>
+#define OBJTYPE void *
+#define OBJLOAD(x) dlopen(x, RTLD_LAZY | RTLD_GLOBAL)
+#define SYMLOAD(x,y) dlsym(x,y)
+#define OBJFREE(x) dlclose(x)
+#else
+
+#error "Your platform has no lib loading code or it is disabled"
+#endif
+
+#if defined __linux__ || defined __FreeBSD__ || defined MACOS_X
+#include <unistd.h>
+#include <sys/types.h>
+#endif
+
+char* (*qcurl_version)(void);
+
+CURL* (*qcurl_easy_init)(void);
+CURLcode (*qcurl_easy_setopt)(CURL *curl, CURLoption option, ...);
+CURLcode (*qcurl_easy_perform)(CURL *curl);
+void (*qcurl_easy_cleanup)(CURL *curl);
+CURLcode (*qcurl_easy_getinfo)(CURL *curl, CURLINFO info, ...);
+CURL* (*qcurl_easy_duphandle)(CURL *curl);
+void (*qcurl_easy_reset)(CURL *curl);
+const char *(*qcurl_easy_strerror)(CURLcode);
+
+CURLM* (*qcurl_multi_init)(void);
+CURLMcode (*qcurl_multi_add_handle)(CURLM *multi_handle,
+                                                CURL *curl_handle);
+CURLMcode (*qcurl_multi_remove_handle)(CURLM *multi_handle,
+                                                CURL *curl_handle);
+CURLMcode (*qcurl_multi_fdset)(CURLM *multi_handle,
+                                                fd_set *read_fd_set,
+                                                fd_set *write_fd_set,
+                                                fd_set *exc_fd_set,
+                                                int *max_fd);
+CURLMcode (*qcurl_multi_perform)(CURLM *multi_handle,
+                                                int *running_handles);
+CURLMcode (*qcurl_multi_cleanup)(CURLM *multi_handle);
+CURLMsg *(*qcurl_multi_info_read)(CURLM *multi_handle,
+                                                int *msgs_in_queue);
+const char *(*qcurl_multi_strerror)(CURLMcode);
+
+static OBJTYPE cURLLib = NULL;
+
+/*
+=================
+GPA
+=================
+*/
+static void *GPA(char *str)
+{
+	void *rv;
+
+	rv = SYMLOAD(cURLLib, str);
+	if(!rv)
+	{
+		Com_Printf("Can't load symbol %s\n", str);
+		clc.cURLEnabled = qfalse;
+		return NULL;
+	}
+	else
+	{
+		Com_DPrintf("Loaded symbol %s (0x%08X)\n", str, rv);
+        return rv;
+	}
+}
+#endif /* USE_CURL_DLOPEN */
+
+/*
+=================
+CL_cURL_Init
+=================
+*/
+qboolean CL_cURL_Init()
+{
+#if USE_CURL_DLOPEN
+	if(cURLLib)
+		return qtrue;
+
+
+	Com_Printf("Loading \"%s\"...", cl_cURLLib->string);
+	if( (cURLLib = OBJLOAD(cl_cURLLib->string)) == 0 )
+	{
+#ifdef _WIN32
+		return qfalse;
+#else
+		char fn[1024];
+		getcwd(fn, sizeof(fn));
+		strncat(fn, "/", sizeof(fn));
+		strncat(fn, cl_cURLLib->string, sizeof(fn));
+
+		if( (cURLLib = OBJLOAD(fn)) == 0 )
+		{
+			return qfalse;
+		}
+#endif /* _WIN32 */
+	}
+
+	clc.cURLEnabled = qtrue;
+
+	qcurl_version = GPA("curl_version");
+
+	qcurl_easy_init = GPA("curl_easy_init");
+	qcurl_easy_setopt = GPA("curl_easy_setopt");
+	qcurl_easy_perform = GPA("curl_easy_perform");
+	qcurl_easy_cleanup = GPA("curl_easy_cleanup");
+	qcurl_easy_getinfo = GPA("curl_easy_getinfo");
+	qcurl_easy_duphandle = GPA("curl_easy_duphandle");
+	qcurl_easy_reset = GPA("curl_easy_reset");
+	qcurl_easy_strerror = GPA("curl_easy_strerror");
+	
+	qcurl_multi_init = GPA("curl_multi_init");
+	qcurl_multi_add_handle = GPA("curl_multi_add_handle");
+	qcurl_multi_remove_handle = GPA("curl_multi_remove_handle");
+	qcurl_multi_fdset = GPA("curl_multi_fdset");
+	qcurl_multi_perform = GPA("curl_multi_perform");
+	qcurl_multi_cleanup = GPA("curl_multi_cleanup");
+	qcurl_multi_info_read = GPA("curl_multi_info_read");
+	qcurl_multi_strerror = GPA("curl_multi_strerror");
+
+	if(!clc.cURLEnabled)
+	{
+		CL_cURL_Shutdown();
+		Com_Printf("FAIL One or more symbols not found\n");
+		return qfalse;
+	}
+	Com_Printf("OK\n");
+
+	return qtrue;
+#else
+	clc.cURLEnabled = qtrue;
+	return qtrue;
+#endif /* USE_CURL_DLOPEN */
+}
+
+/*
+=================
+CL_cURL_Shutdown
+=================
+*/
+void CL_cURL_Shutdown( void )
+{
+	CL_cURL_Cleanup();
+#if USE_CURL_DLOPEN
+	if(cURLLib)
+	{
+		OBJFREE(cURLLib);
+		cURLLib = NULL;
+	}
+	qcurl_easy_init = NULL;
+	qcurl_easy_setopt = NULL;
+	qcurl_easy_perform = NULL;
+	qcurl_easy_cleanup = NULL;
+	qcurl_easy_getinfo = NULL;
+	qcurl_easy_duphandle = NULL;
+	qcurl_easy_reset = NULL;
+
+	qcurl_multi_init = NULL;
+	qcurl_multi_add_handle = NULL;
+	qcurl_multi_remove_handle = NULL;
+	qcurl_multi_fdset = NULL;
+	qcurl_multi_perform = NULL;
+	qcurl_multi_cleanup = NULL;
+	qcurl_multi_info_read = NULL;
+	qcurl_multi_strerror = NULL;
+#endif /* USE_CURL_DLOPEN */
+}
+
+void CL_cURL_Cleanup(void)
+{
+	if(clc.downloadCURLM) {
+		if(clc.downloadCURL) {
+			qcurl_multi_remove_handle(clc.downloadCURLM,
+				clc.downloadCURL);
+			qcurl_easy_cleanup(clc.downloadCURL);
+		}
+		qcurl_multi_cleanup(clc.downloadCURLM);
+		clc.downloadCURLM = NULL;
+		clc.downloadCURL = NULL;
+	}
+	else if(clc.downloadCURL) {
+		qcurl_easy_cleanup(clc.downloadCURL);
+		clc.downloadCURL = NULL;
+	}
+}
+
+static int CL_cURL_CallbackProgress( void *dummy, double dltotal, double dlnow,
+	double ultotal, double ulnow )
+{
+	clc.downloadSize = (int)dltotal;
+	Cvar_SetValue( "cl_downloadSize", clc.downloadSize );
+	clc.downloadCount = (int)dlnow;
+	Cvar_SetValue( "cl_downloadCount", clc.downloadCount );
+	return 0;
+}
+
+static int CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb,
+	void *stream)
+{
+	FS_Write( buffer, size*nmemb, ((fileHandle_t*)stream)[0] );
+	return size*nmemb;
+}
+
+void CL_cURL_BeginDownload( const char *localName, const char *remoteURL )
+{
+	clc.cURLUsed = qtrue;
+	Com_Printf("URL: %s\n", remoteURL);
+	Com_DPrintf("***** CL_cURL_BeginDownload *****\n"
+		"Localname: %s\n"
+		"RemoteURL: %s\n"
+		"****************************\n", localName, remoteURL);
+	CL_cURL_Cleanup();
+	Q_strncpyz(clc.downloadURL, remoteURL, sizeof(clc.downloadURL));
+	Q_strncpyz(clc.downloadName, localName, sizeof(clc.downloadName));
+	Com_sprintf(clc.downloadTempName, sizeof(clc.downloadTempName),
+		"%s.tmp", localName);
+
+	// Set so UI gets access to it
+	Cvar_Set("cl_downloadName", localName);
+	Cvar_Set("cl_downloadSize", "0");
+	Cvar_Set("cl_downloadCount", "0");
+	Cvar_SetValue("cl_downloadTime", cls.realtime);
+
+	clc.downloadBlock = 0; // Starting new file
+	clc.downloadCount = 0;
+
+	clc.downloadCURL = qcurl_easy_init();
+	if(!clc.downloadCURL) {
+		Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_easy_init() "
+			"failed\n");
+		return;
+	}
+	clc.download = FS_SV_FOpenFileWrite(clc.downloadTempName);
+	if(!clc.download) {
+		Com_Error(ERR_DROP, "CL_cURL_BeginDownload: failed to open "
+			"%s for writing\n", clc.downloadTempName);
+		return;
+	}
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, clc.download);
+	if(com_developer->integer)
+		qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, va("ioQ3://%s",
+		NET_AdrToString(clc.serverAddress)));
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s",
+		Q3_VERSION, qcurl_version()));
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION,
+		CL_cURL_CallbackWrite);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION,
+		CL_cURL_CallbackProgress);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL);
+	qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1);
+	clc.downloadCURLM = qcurl_multi_init();	
+	if(!clc.downloadCURLM) {
+		qcurl_easy_cleanup(clc.downloadCURL);
+		clc.downloadCURL = NULL;
+		Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_multi_init() "
+			"failed\n");
+		return;
+	}
+	qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL);
+
+	if(!(clc.sv_allowDownload & DLF_NO_DISCONNECT) &&
+		!clc.cURLDisconnected) {
+
+		CL_AddReliableCommand("disconnect");
+		CL_WritePacket();
+		CL_WritePacket();
+		CL_WritePacket();
+		clc.cURLDisconnected = qtrue;
+	}
+}
+
+void CL_cURL_PerformDownload(void)
+{
+	CURLMcode res;
+	CURLMsg *msg;
+	int c;
+	int i = 0;
+
+	res = qcurl_multi_perform(clc.downloadCURLM, &c);
+	while(res == CURLM_CALL_MULTI_PERFORM && i < 100) {
+		res = qcurl_multi_perform(clc.downloadCURLM, &c);
+		i++;
+	}
+	if(res == CURLM_CALL_MULTI_PERFORM)
+		return;
+	msg = qcurl_multi_info_read(clc.downloadCURLM, &c);
+	if(msg == NULL) {
+		return;
+	}
+	FS_FCloseFile(clc.download);
+	if(msg->msg == CURLMSG_DONE && msg->data.result == CURLE_OK) {
+		FS_SV_Rename(clc.downloadTempName, clc.downloadName);
+		clc.downloadRestart = qtrue;
+	}
+	else {
+		long code;
+
+		qcurl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE,
+			&code);	
+		Com_Error(ERR_DROP, "Download Error: %s Code: %d URL: %s",
+			qcurl_easy_strerror(msg->data.result),
+			code, clc.downloadURL);
+	}
+	*clc.downloadTempName = *clc.downloadName = 0;
+	Cvar_Set( "cl_downloadName", "" );
+	CL_NextDownload();
+}
+#endif /* USE_CURL */

Added: trunk/code/client/cl_curl.h
===================================================================
--- trunk/code/client/cl_curl.h	                        (rev 0)
+++ trunk/code/client/cl_curl.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,101 @@
+/*
+===========================================================================
+Copyright (C) 2006 Tony J. White (tjw at tjw.org)
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+
+#ifndef __QCURL_H__
+#define __QCURL_H__
+
+extern cvar_t *cl_cURLLib;
+
+#include "../qcommon/q_shared.h"
+#include "../qcommon/qcommon.h"
+
+#ifdef WIN32
+#define DEFAULT_CURL_LIB "libcurl-3.dll"
+#elif defined(MACOS_X)
+#define DEFAULT_CURL_LIB "libcurl.dylib"
+#else
+#define DEFAULT_CURL_LIB "libcurl.so.3"
+#endif
+
+#if USE_LOCAL_HEADERS
+  #include "../libcurl/curl/curl.h"
+#else
+  #include <curl/curl.h>
+#endif
+
+
+#if USE_CURL_DLOPEN
+extern char* (*qcurl_version)(void);
+
+extern CURL* (*qcurl_easy_init)(void);
+extern CURLcode (*qcurl_easy_setopt)(CURL *curl, CURLoption option, ...);
+extern CURLcode (*qcurl_easy_perform)(CURL *curl);
+extern void (*qcurl_easy_cleanup)(CURL *curl);
+extern CURLcode (*qcurl_easy_getinfo)(CURL *curl, CURLINFO info, ...);
+extern void (*qcurl_easy_reset)(CURL *curl);
+extern const char *(*qcurl_easy_strerror)(CURLcode);
+
+extern CURLM* (*qcurl_multi_init)(void);
+extern CURLMcode (*qcurl_multi_add_handle)(CURLM *multi_handle,
+						CURL *curl_handle);
+extern CURLMcode (*qcurl_multi_remove_handle)(CURLM *multi_handle,
+						CURL *curl_handle);
+extern CURLMcode (*qcurl_multi_fdset)(CURLM *multi_handle,
+						fd_set *read_fd_set,
+						fd_set *write_fd_set,
+						fd_set *exc_fd_set,
+						int *max_fd);
+extern CURLMcode (*qcurl_multi_perform)(CURLM *multi_handle,
+						int *running_handles);
+extern CURLMcode (*qcurl_multi_cleanup)(CURLM *multi_handle);
+extern CURLMsg *(*qcurl_multi_info_read)(CURLM *multi_handle,
+						int *msgs_in_queue);
+extern const char *(*qcurl_multi_strerror)(CURLMcode);
+#else
+#define qcurl_version curl_version
+
+#define qcurl_easy_init curl_easy_init
+#define qcurl_easy_setopt curl_easy_setopt
+#define qcurl_easy_perform curl_easy_perform
+#define qcurl_easy_cleanup curl_easy_cleanup
+#define qcurl_easy_getinfo curl_easy_getinfo
+#define qcurl_easy_duphandle curl_easy_duphandle
+#define qcurl_easy_reset curl_easy_reset
+#define qcurl_easy_strerror curl_easy_strerror
+
+#define qcurl_multi_init curl_multi_init
+#define qcurl_multi_add_handle curl_multi_add_handle
+#define qcurl_multi_remove_handle curl_multi_remove_handle
+#define qcurl_multi_fdset curl_multi_fdset
+#define qcurl_multi_perform curl_multi_perform
+#define qcurl_multi_cleanup curl_multi_cleanup
+#define qcurl_multi_info_read curl_multi_info_read
+#define qcurl_multi_strerror curl_multi_strerror
+#endif
+
+qboolean CL_cURL_Init( void );
+void CL_cURL_Shutdown( void );
+void CL_cURL_BeginDownload( const char *localName, const char *remoteURL );
+void CL_cURL_PerformDownload( void );
+void CL_cURL_Cleanup( void );
+#endif	// __QCURL_H__

Modified: trunk/code/client/cl_main.c
===================================================================
--- trunk/code/client/cl_main.c	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/code/client/cl_main.c	2006-09-11 16:41:55 UTC (rev 898)
@@ -608,6 +608,9 @@
 */
 void CL_ShutdownAll(void) {
 
+#if USE_CURL
+	CL_cURL_Shutdown();
+#endif
 	// clear sounds
 	S_DisableSounds();
 	// shutdown CGame
@@ -1331,6 +1334,23 @@
 */
 void CL_DownloadsComplete( void ) {
 
+#if USE_CURL
+	// if we downloaded with cURL
+	if(clc.cURLUsed) { 
+		clc.cURLUsed = qfalse;
+		CL_cURL_Shutdown();
+		if( clc.cURLDisconnected ) {
+			if(clc.downloadRestart) {
+				FS_Restart(clc.checksumFeed);
+				clc.downloadRestart = qfalse;
+			}
+			clc.cURLDisconnected = qfalse;
+			CL_Reconnect_f();
+			return;
+		}
+	}
+#endif
+
 	// if we downloaded files we need to restart the file system
 	if (clc.downloadRestart) {
 		clc.downloadRestart = qfalse;
@@ -1418,6 +1438,7 @@
 void CL_NextDownload(void) {
 	char *s;
 	char *remoteName, *localName;
+	qboolean useCURL = qfalse;
 
 	// We are looking to start a download here
 	if (*clc.downloadList) {
@@ -1441,9 +1462,48 @@
 			*s++ = 0;
 		else
 			s = localName + strlen(localName); // point at the nul byte
-		
-		CL_BeginDownload( localName, remoteName );
-
+#if USE_CURL
+		if(!(cl_allowDownload->integer & DLF_NO_REDIRECT)) {
+			if(clc.sv_allowDownload & DLF_NO_REDIRECT) {
+				Com_Printf("WARNING: server does not "
+					"allow download redirection "
+					"(sv_allowDownload is %d)\n",
+					clc.sv_allowDownload);
+			}
+			else if(!*clc.sv_dlURL) {
+				Com_Printf("WARNING: server allows "
+					"download redirection, but does not "
+					"have sv_dlURL set\n");
+			}
+			else if(!CL_cURL_Init()) {
+				Com_Printf("WARNING: could not load "
+					"cURL library\n");
+			}
+			else {
+				CL_cURL_BeginDownload(localName, va("%s/%s",
+					clc.sv_dlURL, remoteName));
+				useCURL = qtrue;
+			}
+		}
+		else if(!(clc.sv_allowDownload & DLF_NO_REDIRECT)) {
+			Com_Printf("WARNING: server allows download "
+				"redirection, but it disabled by client "
+				"configuration (cl_allowDownload is %d)\n",
+				cl_allowDownload->integer);
+		}
+#endif /* USE_CURL */
+		if(!useCURL) {
+			if((cl_allowDownload->integer & DLF_NO_UDP)) {
+				Com_Error(ERR_DROP, "UDP Downloads are "
+					"disabled on your client. "
+					"(cl_allowDownload is %d)",
+					cl_allowDownload->integer);
+				return;	
+			}
+			else {
+				CL_BeginDownload( localName, remoteName );
+			}
+		}
 		clc.downloadRestart = qtrue;
 
 		// move over the rest
@@ -1466,7 +1526,7 @@
 void CL_InitDownloads(void) {
   char missingfiles[1024];
 
-  if ( !cl_allowDownload->integer )
+  if ( !(cl_allowDownload->integer & DLF_ENABLE) )
   {
     // autodownload is disabled on the client
     // but it's possible that some referenced files on the server are missing
@@ -2028,6 +2088,25 @@
 		return;
 	}
 
+#if USE_CURL
+	if(clc.downloadCURLM) {
+		CL_cURL_PerformDownload();
+		// we can't process frames normally when in disconnected
+		// download mode since the ui vm expects cls.state to be
+		// CA_CONNECTED
+		if(clc.cURLDisconnected) {
+			cls.realFrametime = msec;
+			cls.frametime = msec;
+			cls.realtime += cls.frametime;
+			SCR_UpdateScreen();
+			S_Update();
+			Con_RunConsole();
+			cls.framecount++;
+			return;
+		}
+	}
+#endif
+
 	if ( cls.cddialog ) {
 		// bring up the cd error dialog if needed
 		cls.cddialog = qfalse;
@@ -2478,6 +2557,9 @@
 	cl_showMouseRate = Cvar_Get ("cl_showmouserate", "0", 0);
 
 	cl_allowDownload = Cvar_Get ("cl_allowDownload", "0", CVAR_ARCHIVE);
+#if USE_CURL
+	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE);
+#endif
 
 	cl_conXOffset = Cvar_Get ("cl_conXOffset", "0", 0);
 #ifdef MACOS_X

Modified: trunk/code/client/cl_parse.c
===================================================================
--- trunk/code/client/cl_parse.c	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/code/client/cl_parse.c	2006-09-11 16:41:55 UTC (rev 898)
@@ -414,6 +414,25 @@
 
 /*
 ==================
+CL_ParseServerInfo
+==================
+*/
+static void CL_ParseServerInfo(void)
+{
+	const char *serverInfo;
+
+	serverInfo = cl.gameState.stringData
+		+ cl.gameState.stringOffsets[ CS_SERVERINFO ];
+
+	clc.sv_allowDownload = atoi(Info_ValueForKey(serverInfo,
+		"sv_allowDownload"));
+	Q_strncpyz(clc.sv_dlURL,
+		Info_ValueForKey(serverInfo, "sv_dlURL"),
+		sizeof(clc.sv_dlURL));
+}
+
+/*
+==================
 CL_ParseGamestate
 ==================
 */
@@ -479,6 +498,9 @@
 	// read the checksum feed
 	clc.checksumFeed = MSG_ReadLong( msg );
 
+	// parse useful values out of CS_SERVERINFO
+	CL_ParseServerInfo();
+
 	// parse serverId and other cvars
 	CL_SystemInfoChanged();
 

Modified: trunk/code/client/client.h
===================================================================
--- trunk/code/client/client.h	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/code/client/client.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -30,6 +30,10 @@
 #include "../cgame/cg_public.h"
 #include "../game/bg_public.h"
 
+#if USE_CURL
+#include "cl_curl.h"
+#endif /* USE_CURL */
+
 // tjw: file full of random crap that gets used to create cl_guid
 #define QKEY_FILE "qkey"
 
@@ -185,6 +189,16 @@
 	fileHandle_t download;
 	char		downloadTempName[MAX_OSPATH];
 	char		downloadName[MAX_OSPATH];
+#ifdef USE_CURL
+	qboolean	cURLEnabled;
+	qboolean	cURLUsed;
+	qboolean	cURLDisconnected;
+	char		downloadURL[MAX_OSPATH];
+	CURL		*downloadCURL;
+	CURLM		*downloadCURLM;
+#endif /* USE_CURL */
+	int		sv_allowDownload;
+	char		sv_dlURL[MAX_CVAR_VALUE_STRING];
 	int			downloadNumber;
 	int			downloadBlock;	// block we are waiting for
 	int			downloadCount;	// how many bytes we got
@@ -351,6 +365,7 @@
 extern	cvar_t	*cl_activeAction;
 
 extern	cvar_t	*cl_allowDownload;
+extern  cvar_t  *cl_downloadMethod;
 extern	cvar_t	*cl_conXOffset;
 extern	cvar_t	*cl_inGameVideo;
 

Added: trunk/code/libcurl/curl/curl.h
===================================================================
--- trunk/code/libcurl/curl/curl.h	                        (rev 0)
+++ trunk/code/libcurl/curl/curl.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,1563 @@
+#ifndef __CURL_CURL_H
+#define __CURL_CURL_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute 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: curl.h,v 1.304 2006-08-04 16:08:41 giva Exp $
+ ***************************************************************************/
+
+/* If you have problems, all libcurl docs and details are found here:
+   http://curl.haxx.se/libcurl/
+*/
+
+#include "curlver.h" /* the libcurl version defines */
+
+#include <stdio.h>
+#include <limits.h>
+
+/* The include stuff here below is mainly for time_t! */
+#ifdef vms
+# include <types.h>
+# include <time.h>
+#else
+# include <sys/types.h>
+# include <time.h>
+#endif /* defined (vms) */
+
+typedef void CURL;
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Decorate exportable functions for Win32 DLL linking.
+ * This avoids using a .def file for building libcurl.dll.
+ */
+#if (defined(WIN32) || defined(_WIN32)) && !defined(CURL_STATICLIB)
+#if defined(BUILDING_LIBCURL)
+#define CURL_EXTERN  __declspec(dllexport)
+#else
+#define CURL_EXTERN  __declspec(dllimport)
+#endif
+#else
+
+#ifdef CURL_HIDDEN_SYMBOLS
+/*
+ * This definition is used to make external definitions visibile in the
+ * shared library when symbols are hidden by default.  It makes no
+ * difference when compiling applications whether this is set or not,
+ * only when compiling the library.
+ */
+#define CURL_EXTERN CURL_EXTERN_SYMBOL
+#else
+#define CURL_EXTERN
+#endif
+#endif
+
+/*
+ * We want the typedef curl_off_t setup for large file support on all
+ * platforms. We also provide a CURL_FORMAT_OFF_T define to use in *printf
+ * format strings when outputting a variable of type curl_off_t.
+ *
+ * Note: "pocc -Ze" is MSVC compatibily mode and this sets _MSC_VER!
+ */
+
+#if (defined(_MSC_VER) && !defined(__POCC__)) || (defined(__LCC__) && defined(WIN32))
+/* MSVC */
+#ifdef _WIN32_WCE
+  typedef long curl_off_t;
+#define CURL_FORMAT_OFF_T "%ld"
+#else
+  typedef signed __int64 curl_off_t;
+#define CURL_FORMAT_OFF_T "%I64d"
+#endif
+#else /* (_MSC_VER && !__POCC__) || (__LCC__ && WIN32) */
+#if (defined(__GNUC__) && defined(WIN32)) || defined(__WATCOMC__)
+/* gcc on windows or Watcom */
+  typedef long long curl_off_t;
+#define CURL_FORMAT_OFF_T "%I64d"
+#else /* GCC or Watcom on Windows  */
+
+/* "normal" POSIX approach, do note that this does not necessarily mean that
+   the type is >32 bits, see the SIZEOF_CURL_OFF_T define for that! */
+  typedef off_t curl_off_t;
+
+/* Check a range of defines to detect large file support. On Linux it seems
+   none of these are set by default, so if you don't explicitly switches on
+   large file support, this define will be made for "small file" support. */
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 0 /* to prevent warnings in the check below */
+#define UNDEF_FILE_OFFSET_BITS
+#endif
+#ifndef FILESIZEBITS
+#define FILESIZEBITS 0 /* to prevent warnings in the check below */
+#define UNDEF_FILESIZEBITS
+#endif
+
+#if defined(_LARGE_FILES) || (_FILE_OFFSET_BITS > 32) || (FILESIZEBITS > 32) \
+   || defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE)
+  /* For now, we assume at least one of these to be set for large files to
+     work! */
+#define CURL_FORMAT_OFF_T "%lld"
+#else /* LARGE_FILE support */
+#define CURL_FORMAT_OFF_T "%ld"
+#endif
+#endif /* GCC or Watcom on Windows */
+#endif /* (_MSC_VER && !__POCC__) || (__LCC__ && WIN32) */
+
+#ifdef UNDEF_FILE_OFFSET_BITS
+/* this was defined above for our checks, undefine it again */
+#undef _FILE_OFFSET_BITS
+#endif
+
+#ifdef UNDEF_FILESIZEBITS
+/* this was defined above for our checks, undefine it again */
+#undef FILESIZEBITS
+#endif
+
+struct curl_httppost {
+  struct curl_httppost *next;       /* next entry in the list */
+  char *name;                       /* pointer to allocated name */
+  long namelength;                  /* length of name length */
+  char *contents;                   /* pointer to allocated data contents */
+  long contentslength;              /* length of contents field */
+  char *buffer;                     /* pointer to allocated buffer contents */
+  long bufferlength;                /* length of buffer field */
+  char *contenttype;                /* Content-Type */
+  struct curl_slist* contentheader; /* list of extra headers for this form */
+  struct curl_httppost *more;       /* if one field name has more than one
+                                       file, this link should link to following
+                                       files */
+  long flags;                       /* as defined below */
+#define HTTPPOST_FILENAME (1<<0)    /* specified content is a file name */
+#define HTTPPOST_READFILE (1<<1)    /* specified content is a file name */
+#define HTTPPOST_PTRNAME (1<<2)     /* name is only stored pointer
+                                       do not free in formfree */
+#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer
+                                       do not free in formfree */
+#define HTTPPOST_BUFFER (1<<4)      /* upload file from buffer */
+#define HTTPPOST_PTRBUFFER (1<<5)   /* upload file from pointer contents */
+
+  char *showfilename;               /* The file name to show. If not set, the
+                                       actual file name will be used (if this
+                                       is a file part) */
+};
+
+typedef int (*curl_progress_callback)(void *clientp,
+                                      double dltotal,
+                                      double dlnow,
+                                      double ultotal,
+                                      double ulnow);
+
+  /* Tests have proven that 20K is a very bad buffer size for uploads on
+     Windows, while 16K for some odd reason performed a lot better. */
+#define CURL_MAX_WRITE_SIZE 16384
+
+typedef size_t (*curl_write_callback)(char *buffer,
+                                      size_t size,
+                                      size_t nitems,
+                                      void *outstream);
+
+/* This is a return code for the read callback that, when returned, will
+   signal libcurl to immediately abort the current transfer. */
+#define CURL_READFUNC_ABORT 0x10000000
+typedef size_t (*curl_read_callback)(char *buffer,
+                                      size_t size,
+                                      size_t nitems,
+                                      void *instream);
+
+
+#ifndef CURL_NO_OLDIES
+  /* not used since 7.10.8, will be removed in a future release */
+typedef int (*curl_passwd_callback)(void *clientp,
+                                    const char *prompt,
+                                    char *buffer,
+                                    int buflen);
+#endif
+
+typedef enum {
+  CURLIOE_OK,            /* I/O operation successful */
+  CURLIOE_UNKNOWNCMD,    /* command was unknown to callback */
+  CURLIOE_FAILRESTART,   /* failed to restart the read */
+  CURLIOE_LAST           /* never use */
+} curlioerr;
+
+typedef enum  {
+  CURLIOCMD_NOP,         /* no operation */
+  CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+  CURLIOCMD_LAST         /* never use */
+} curliocmd;
+
+typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
+                                         int cmd,
+                                         void *clientp);
+
+/*
+ * The following typedef's are signatures of malloc, free, realloc, strdup and
+ * calloc respectively.  Function pointers of these types can be passed to the
+ * curl_global_init_mem() function to set user defined memory management
+ * callback routines.
+ */
+typedef void *(*curl_malloc_callback)(size_t size);
+typedef void (*curl_free_callback)(void *ptr);
+typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
+typedef char *(*curl_strdup_callback)(const char *str);
+typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
+
+/* the kind of data that is passed to information_callback*/
+typedef enum {
+  CURLINFO_TEXT = 0,
+  CURLINFO_HEADER_IN,    /* 1 */
+  CURLINFO_HEADER_OUT,   /* 2 */
+  CURLINFO_DATA_IN,      /* 3 */
+  CURLINFO_DATA_OUT,     /* 4 */
+  CURLINFO_SSL_DATA_IN,  /* 5 */
+  CURLINFO_SSL_DATA_OUT, /* 6 */
+  CURLINFO_END
+} curl_infotype;
+
+typedef int (*curl_debug_callback)
+       (CURL *handle,      /* the handle/transfer this concerns */
+        curl_infotype type, /* what kind of data */
+        char *data,        /* points to the data */
+        size_t size,       /* size of the data pointed to */
+        void *userptr);    /* whatever the user please */
+
+/* All possible error codes from all sorts of curl functions. Future versions
+   may return other values, stay prepared.
+
+   Always add new return codes last. Never *EVER* remove any. The return
+   codes must remain the same!
+ */
+
+typedef enum {
+  CURLE_OK = 0,
+  CURLE_UNSUPPORTED_PROTOCOL,    /* 1 */
+  CURLE_FAILED_INIT,             /* 2 */
+  CURLE_URL_MALFORMAT,           /* 3 */
+  CURLE_URL_MALFORMAT_USER,      /* 4 - NOT USED */
+  CURLE_COULDNT_RESOLVE_PROXY,   /* 5 */
+  CURLE_COULDNT_RESOLVE_HOST,    /* 6 */
+  CURLE_COULDNT_CONNECT,         /* 7 */
+  CURLE_FTP_WEIRD_SERVER_REPLY,  /* 8 */
+  CURLE_FTP_ACCESS_DENIED,       /* 9 a service was denied by the FTP server
+                                    due to lack of access - when login fails
+                                    this is not returned. */
+  CURLE_FTP_USER_PASSWORD_INCORRECT, /* 10 - NOT USED */
+  CURLE_FTP_WEIRD_PASS_REPLY,    /* 11 */
+  CURLE_FTP_WEIRD_USER_REPLY,    /* 12 */
+  CURLE_FTP_WEIRD_PASV_REPLY,    /* 13 */
+  CURLE_FTP_WEIRD_227_FORMAT,    /* 14 */
+  CURLE_FTP_CANT_GET_HOST,       /* 15 */
+  CURLE_FTP_CANT_RECONNECT,      /* 16 */
+  CURLE_FTP_COULDNT_SET_BINARY,  /* 17 */
+  CURLE_PARTIAL_FILE,            /* 18 */
+  CURLE_FTP_COULDNT_RETR_FILE,   /* 19 */
+  CURLE_FTP_WRITE_ERROR,         /* 20 */
+  CURLE_FTP_QUOTE_ERROR,         /* 21 */
+  CURLE_HTTP_RETURNED_ERROR,     /* 22 */
+  CURLE_WRITE_ERROR,             /* 23 */
+  CURLE_MALFORMAT_USER,          /* 24 - NOT USED */
+  CURLE_FTP_COULDNT_STOR_FILE,   /* 25 - failed FTP upload */
+  CURLE_READ_ERROR,              /* 26 - could open/read from file */
+  CURLE_OUT_OF_MEMORY,           /* 27 */
+  /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+           instead of a memory allocation error if CURL_DOES_CONVERSIONS
+           is defined
+  */
+  CURLE_OPERATION_TIMEOUTED,     /* 28 - the timeout time was reached */
+  CURLE_FTP_COULDNT_SET_ASCII,   /* 29 - TYPE A failed */
+  CURLE_FTP_PORT_FAILED,         /* 30 - FTP PORT operation failed */
+  CURLE_FTP_COULDNT_USE_REST,    /* 31 - the REST command failed */
+  CURLE_FTP_COULDNT_GET_SIZE,    /* 32 - the SIZE command failed */
+  CURLE_HTTP_RANGE_ERROR,        /* 33 - RANGE "command" didn't work */
+  CURLE_HTTP_POST_ERROR,         /* 34 */
+  CURLE_SSL_CONNECT_ERROR,       /* 35 - wrong when connecting with SSL */
+  CURLE_BAD_DOWNLOAD_RESUME,     /* 36 - couldn't resume download */
+  CURLE_FILE_COULDNT_READ_FILE,  /* 37 */
+  CURLE_LDAP_CANNOT_BIND,        /* 38 */
+  CURLE_LDAP_SEARCH_FAILED,      /* 39 */
+  CURLE_LIBRARY_NOT_FOUND,       /* 40 */
+  CURLE_FUNCTION_NOT_FOUND,      /* 41 */
+  CURLE_ABORTED_BY_CALLBACK,     /* 42 */
+  CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */
+  CURLE_BAD_CALLING_ORDER,       /* 44 - NOT USED */
+  CURLE_INTERFACE_FAILED,        /* 45 - CURLOPT_INTERFACE failed */
+  CURLE_BAD_PASSWORD_ENTERED,    /* 46 - NOT USED */
+  CURLE_TOO_MANY_REDIRECTS ,     /* 47 - catch endless re-direct loops */
+  CURLE_UNKNOWN_TELNET_OPTION,   /* 48 - User specified an unknown option */
+  CURLE_TELNET_OPTION_SYNTAX ,   /* 49 - Malformed telnet option */
+  CURLE_OBSOLETE,                /* 50 - NOT USED */
+  CURLE_SSL_PEER_CERTIFICATE,    /* 51 - peer's certificate wasn't ok */
+  CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */
+  CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */
+  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as
+                                    default */
+  CURLE_SEND_ERROR,              /* 55 - failed sending network data */
+  CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */
+  CURLE_SHARE_IN_USE,            /* 57 - share is in use */
+  CURLE_SSL_CERTPROBLEM,         /* 58 - problem with the local certificate */
+  CURLE_SSL_CIPHER,              /* 59 - couldn't use specified cipher */
+  CURLE_SSL_CACERT,              /* 60 - problem with the CA cert (path?) */
+  CURLE_BAD_CONTENT_ENCODING,    /* 61 - Unrecognized transfer encoding */
+  CURLE_LDAP_INVALID_URL,        /* 62 - Invalid LDAP URL */
+  CURLE_FILESIZE_EXCEEDED,       /* 63 - Maximum file size exceeded */
+  CURLE_FTP_SSL_FAILED,          /* 64 - Requested FTP SSL level failed */
+  CURLE_SEND_FAIL_REWIND,        /* 65 - Sending the data requires a rewind
+                                    that failed */
+  CURLE_SSL_ENGINE_INITFAILED,   /* 66 - failed to initialise ENGINE */
+  CURLE_LOGIN_DENIED,            /* 67 - user, password or similar was not
+                                    accepted and we failed to login */
+  CURLE_TFTP_NOTFOUND,           /* 68 - file not found on server */
+  CURLE_TFTP_PERM,               /* 69 - permission problem on server */
+  CURLE_TFTP_DISKFULL,           /* 70 - out of disk space on server */
+  CURLE_TFTP_ILLEGAL,            /* 71 - Illegal TFTP operation */
+  CURLE_TFTP_UNKNOWNID,          /* 72 - Unknown transfer ID */
+  CURLE_TFTP_EXISTS,             /* 73 - File already exists */
+  CURLE_TFTP_NOSUCHUSER,         /* 74 - No such user */
+  CURLE_CONV_FAILED,             /* 75 - conversion failed */
+  CURLE_CONV_REQD,               /* 76 - caller must register conversion
+                                    callbacks using curl_easy_setopt options
+                                    CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+                                    CURLOPT_CONV_TO_NETWORK_FUNCTION, and
+                                    CURLOPT_CONV_FROM_UTF8_FUNCTION */
+  CURL_LAST /* never use! */
+} CURLcode;
+
+/* This prototype applies to all conversion callbacks */
+typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
+
+typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl,    /* easy handle */
+                                          void *ssl_ctx, /* actually an
+                                                            OpenSSL SSL_CTX */
+                                          void *userptr);
+
+/* Make a spelling correction for the operation timed-out define */
+#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+                          the obsolete stuff removed! */
+/* backwards compatibility with older names */
+#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
+#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
+#endif
+
+typedef enum {
+  CURLPROXY_HTTP = 0,
+  CURLPROXY_SOCKS4 = 4,
+  CURLPROXY_SOCKS5 = 5
+} curl_proxytype;
+
+#define CURLAUTH_NONE         0       /* nothing */
+#define CURLAUTH_BASIC        (1<<0)  /* Basic (default) */
+#define CURLAUTH_DIGEST       (1<<1)  /* Digest */
+#define CURLAUTH_GSSNEGOTIATE (1<<2)  /* GSS-Negotiate */
+#define CURLAUTH_NTLM         (1<<3)  /* NTLM */
+#define CURLAUTH_ANY ~0               /* all types set */
+#define CURLAUTH_ANYSAFE (~CURLAUTH_BASIC)
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+                          the obsolete stuff removed! */
+/* this was the error code 50 in 7.7.3 and a few earlier versions, this
+   is no longer used by libcurl but is instead #defined here only to not
+   make programs break */
+#define CURLE_ALREADY_COMPLETE 99999
+
+/* These are just to make older programs not break: */
+#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
+#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
+#endif
+
+#define CURL_ERROR_SIZE 256
+
+/* parameter for the CURLOPT_FTP_SSL option */
+typedef enum {
+  CURLFTPSSL_NONE,    /* do not attempt to use SSL */
+  CURLFTPSSL_TRY,     /* try using SSL, proceed anyway otherwise */
+  CURLFTPSSL_CONTROL, /* SSL for the control connection or fail */
+  CURLFTPSSL_ALL,     /* SSL for all communication or fail */
+  CURLFTPSSL_LAST     /* not an option, never use */
+} curl_ftpssl;
+
+/* parameter for the CURLOPT_FTPSSLAUTH option */
+typedef enum {
+  CURLFTPAUTH_DEFAULT, /* let libcurl decide */
+  CURLFTPAUTH_SSL,     /* use "AUTH SSL" */
+  CURLFTPAUTH_TLS,     /* use "AUTH TLS" */
+  CURLFTPAUTH_LAST /* not an option, never use */
+} curl_ftpauth;
+
+/* parameter for the CURLOPT_FTP_FILEMETHOD option */
+typedef enum {
+  CURLFTPMETHOD_DEFAULT,   /* let libcurl pick */
+  CURLFTPMETHOD_MULTICWD,  /* single CWD operation for each path part */
+  CURLFTPMETHOD_NOCWD,     /* no CWD at all */
+  CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
+  CURLFTPMETHOD_LAST       /* not an option, never use */
+} curl_ftpmethod;
+
+/* long may be 32 or 64 bits, but we should never depend on anything else
+   but 32 */
+#define CURLOPTTYPE_LONG          0
+#define CURLOPTTYPE_OBJECTPOINT   10000
+#define CURLOPTTYPE_FUNCTIONPOINT 20000
+#define CURLOPTTYPE_OFF_T         30000
+
+/* name is uppercase CURLOPT_<name>,
+   type is one of the defined CURLOPTTYPE_<type>
+   number is unique identifier */
+#ifdef CINIT
+#undef CINIT
+#endif
+/*
+ * Figure out if we can use the ## operator, which is supported by ISO/ANSI C
+ * and C++. Some compilers support it without setting __STDC__ or __cplusplus
+ * so we need to carefully check for them too. We don't use configure-checks
+ * for these since we want these headers to remain generic and working for all
+ * platforms.
+ */
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
+  defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
+  defined(__POCC__) || defined(__SALFORDC__)
+  /* This compiler is believed to have an ISO compatible preprocessor */
+#define CURL_ISOCPP
+#else
+  /* This compiler is believed NOT to have an ISO compatible preprocessor */
+#undef CURL_ISOCPP
+#endif
+
+#ifdef CURL_ISOCPP
+#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG          CURLOPTTYPE_LONG
+#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T         CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLOPT_/**/name = type + number
+#endif
+
+/*
+ * This macro-mania below setups the CURLOPT_[what] enum, to be used with
+ * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
+ * word.
+ */
+
+typedef enum {
+  /* This is the FILE * or void * the regular output should be written to. */
+  CINIT(FILE, OBJECTPOINT, 1),
+
+  /* The full URL to get/put */
+  CINIT(URL,  OBJECTPOINT, 2),
+
+  /* Port number to connect to, if other than default. */
+  CINIT(PORT, LONG, 3),
+
+  /* Name of proxy to use. */
+  CINIT(PROXY, OBJECTPOINT, 4),
+
+  /* "name:password" to use when fetching. */
+  CINIT(USERPWD, OBJECTPOINT, 5),
+
+  /* "name:password" to use with proxy. */
+  CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
+
+  /* Range to get, specified as an ASCII string. */
+  CINIT(RANGE, OBJECTPOINT, 7),
+
+  /* not used */
+
+  /* Specified file stream to upload from (use as input): */
+  CINIT(INFILE, OBJECTPOINT, 9),
+
+  /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
+   * bytes big. If this is not used, error messages go to stderr instead: */
+  CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+
+  /* Function that will be called to store the output (instead of fwrite). The
+   * parameters will use fwrite() syntax, make sure to follow them. */
+  CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+
+  /* Function that will be called to read the input (instead of fread). The
+   * parameters will use fread() syntax, make sure to follow them. */
+  CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+
+  /* Time-out the read operation after this amount of seconds */
+  CINIT(TIMEOUT, LONG, 13),
+
+  /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
+   * how large the file being sent really is. That allows better error
+   * checking and better verifies that the upload was succcessful. -1 means
+   * unknown size.
+   *
+   * For large file support, there is also a _LARGE version of the key
+   * which takes an off_t type, allowing platforms with larger off_t
+   * sizes to handle larger files.  See below for INFILESIZE_LARGE.
+   */
+  CINIT(INFILESIZE, LONG, 14),
+
+  /* POST input fields. */
+  CINIT(POSTFIELDS, OBJECTPOINT, 15),
+
+  /* Set the referer page (needed by some CGIs) */
+  CINIT(REFERER, OBJECTPOINT, 16),
+
+  /* Set the FTP PORT string (interface name, named or numerical IP address)
+     Use i.e '-' to use default address. */
+  CINIT(FTPPORT, OBJECTPOINT, 17),
+
+  /* Set the User-Agent string (examined by some CGIs) */
+  CINIT(USERAGENT, OBJECTPOINT, 18),
+
+  /* If the download receives less than "low speed limit" bytes/second
+   * during "low speed time" seconds, the operations is aborted.
+   * You could i.e if you have a pretty high speed connection, abort if
+   * it is less than 2000 bytes/sec during 20 seconds.
+   */
+
+  /* Set the "low speed limit" */
+  CINIT(LOW_SPEED_LIMIT, LONG , 19),
+
+  /* Set the "low speed time" */
+  CINIT(LOW_SPEED_TIME, LONG, 20),
+
+  /* Set the continuation offset.
+   *
+   * Note there is also a _LARGE version of this key which uses
+   * off_t types, allowing for large file offsets on platforms which
+   * use larger-than-32-bit off_t's.  Look below for RESUME_FROM_LARGE.
+   */
+  CINIT(RESUME_FROM, LONG, 21),
+
+  /* Set cookie in request: */
+  CINIT(COOKIE, OBJECTPOINT, 22),
+
+  /* This points to a linked list of headers, struct curl_slist kind */
+  CINIT(HTTPHEADER, OBJECTPOINT, 23),
+
+  /* This points to a linked list of post entries, struct HttpPost */
+  CINIT(HTTPPOST, OBJECTPOINT, 24),
+
+  /* name of the file keeping your private SSL-certificate */
+  CINIT(SSLCERT, OBJECTPOINT, 25),
+
+  /* password for the SSL-private key, keep this for compatibility */
+  CINIT(SSLCERTPASSWD, OBJECTPOINT, 26),
+  /* password for the SSL private key */
+  CINIT(SSLKEYPASSWD, OBJECTPOINT, 26),
+
+  /* send TYPE parameter? */
+  CINIT(CRLF, LONG, 27),
+
+  /* send linked-list of QUOTE commands */
+  CINIT(QUOTE, OBJECTPOINT, 28),
+
+  /* send FILE * or void * to store headers to, if you use a callback it
+     is simply passed to the callback unmodified */
+  CINIT(WRITEHEADER, OBJECTPOINT, 29),
+
+  /* point to a file to read the initial cookies from, also enables
+     "cookie awareness" */
+  CINIT(COOKIEFILE, OBJECTPOINT, 31),
+
+  /* What version to specifly try to use.
+     See CURL_SSLVERSION defines below. */
+  CINIT(SSLVERSION, LONG, 32),
+
+  /* What kind of HTTP time condition to use, see defines */
+  CINIT(TIMECONDITION, LONG, 33),
+
+  /* Time to use with the above condition. Specified in number of seconds
+     since 1 Jan 1970 */
+  CINIT(TIMEVALUE, LONG, 34),
+
+  /* 35 = OBSOLETE */
+
+  /* Custom request, for customizing the get command like
+     HTTP: DELETE, TRACE and others
+     FTP: to use a different list command
+     */
+  CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
+
+  /* HTTP request, for odd commands like DELETE, TRACE and others */
+  CINIT(STDERR, OBJECTPOINT, 37),
+
+  /* 38 is not used */
+
+  /* send linked-list of post-transfer QUOTE commands */
+  CINIT(POSTQUOTE, OBJECTPOINT, 39),
+
+  /* Pass a pointer to string of the output using full variable-replacement
+     as described elsewhere. */
+  CINIT(WRITEINFO, OBJECTPOINT, 40),
+
+  CINIT(VERBOSE, LONG, 41),      /* talk a lot */
+  CINIT(HEADER, LONG, 42),       /* throw the header out too */
+  CINIT(NOPROGRESS, LONG, 43),   /* shut off the progress meter */
+  CINIT(NOBODY, LONG, 44),       /* use HEAD to get http document */
+  CINIT(FAILONERROR, LONG, 45),  /* no output on http error codes >= 300 */
+  CINIT(UPLOAD, LONG, 46),       /* this is an upload */
+  CINIT(POST, LONG, 47),         /* HTTP POST method */
+  CINIT(FTPLISTONLY, LONG, 48),  /* Use NLST when listing ftp dir */
+
+  CINIT(FTPAPPEND, LONG, 50),    /* Append instead of overwrite on upload! */
+
+  /* Specify whether to read the user+password from the .netrc or the URL.
+   * This must be one of the CURL_NETRC_* enums below. */
+  CINIT(NETRC, LONG, 51),
+
+  CINIT(FOLLOWLOCATION, LONG, 52),  /* use Location: Luke! */
+
+  CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
+  CINIT(PUT, LONG, 54),          /* HTTP PUT */
+
+  /* 55 = OBSOLETE */
+
+  /* Function that will be called instead of the internal progress display
+   * function. This function should be defined as the curl_progress_callback
+   * prototype defines. */
+  CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+
+  /* Data passed to the progress callback */
+  CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+
+  /* We want the referer field set automatically when following locations */
+  CINIT(AUTOREFERER, LONG, 58),
+
+  /* Port of the proxy, can be set in the proxy string as well with:
+     "[host]:[port]" */
+  CINIT(PROXYPORT, LONG, 59),
+
+  /* size of the POST input data, if strlen() is not good to use */
+  CINIT(POSTFIELDSIZE, LONG, 60),
+
+  /* tunnel non-http operations through a HTTP proxy */
+  CINIT(HTTPPROXYTUNNEL, LONG, 61),
+
+  /* Set the interface string to use as outgoing network interface */
+  CINIT(INTERFACE, OBJECTPOINT, 62),
+
+  /* Set the krb4 security level, this also enables krb4 awareness.  This is a
+   * string, 'clear', 'safe', 'confidential' or 'private'.  If the string is
+   * set but doesn't match one of these, 'private' will be used.  */
+  CINIT(KRB4LEVEL, OBJECTPOINT, 63),
+
+  /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
+  CINIT(SSL_VERIFYPEER, LONG, 64),
+
+  /* The CApath or CAfile used to validate the peer certificate
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(CAINFO, OBJECTPOINT, 65),
+
+  /* 66 = OBSOLETE */
+  /* 67 = OBSOLETE */
+
+  /* Maximum number of http redirects to follow */
+  CINIT(MAXREDIRS, LONG, 68),
+
+  /* Pass a long set to 1 to get the date of the requested document (if
+     possible)! Pass a zero to shut it off. */
+  CINIT(FILETIME, LONG, 69),
+
+  /* This points to a linked list of telnet options */
+  CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
+
+  /* Max amount of cached alive connections */
+  CINIT(MAXCONNECTS, LONG, 71),
+
+  /* What policy to use when closing connections when the cache is filled
+     up */
+  CINIT(CLOSEPOLICY, LONG, 72),
+
+  /* 73 = OBSOLETE */
+
+  /* Set to explicitly use a new connection for the upcoming transfer.
+     Do not use this unless you're absolutely sure of this, as it makes the
+     operation slower and is less friendly for the network. */
+  CINIT(FRESH_CONNECT, LONG, 74),
+
+  /* Set to explicitly forbid the upcoming transfer's connection to be re-used
+     when done. Do not use this unless you're absolutely sure of this, as it
+     makes the operation slower and is less friendly for the network. */
+  CINIT(FORBID_REUSE, LONG, 75),
+
+  /* Set to a file name that contains random data for libcurl to use to
+     seed the random engine when doing SSL connects. */
+  CINIT(RANDOM_FILE, OBJECTPOINT, 76),
+
+  /* Set to the Entropy Gathering Daemon socket pathname */
+  CINIT(EGDSOCKET, OBJECTPOINT, 77),
+
+  /* Time-out connect operations after this amount of seconds, if connects
+     are OK within this time, then fine... This only aborts the connect
+     phase. [Only works on unix-style/SIGALRM operating systems] */
+  CINIT(CONNECTTIMEOUT, LONG, 78),
+
+  /* Function that will be called to store headers (instead of fwrite). The
+   * parameters will use fwrite() syntax, make sure to follow them. */
+  CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+
+  /* Set this to force the HTTP request to get back to GET. Only really usable
+     if POST, PUT or a custom request have been used first.
+   */
+  CINIT(HTTPGET, LONG, 80),
+
+  /* Set if we should verify the Common name from the peer certificate in ssl
+   * handshake, set 1 to check existence, 2 to ensure that it matches the
+   * provided hostname. */
+  CINIT(SSL_VERIFYHOST, LONG, 81),
+
+  /* Specify which file name to write all known cookies in after completed
+     operation. Set file name to "-" (dash) to make it go to stdout. */
+  CINIT(COOKIEJAR, OBJECTPOINT, 82),
+
+  /* Specify which SSL ciphers to use */
+  CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83),
+
+  /* Specify which HTTP version to use! This must be set to one of the
+     CURL_HTTP_VERSION* enums set below. */
+  CINIT(HTTP_VERSION, LONG, 84),
+
+  /* Specificly switch on or off the FTP engine's use of the EPSV command. By
+     default, that one will always be attempted before the more traditional
+     PASV command. */
+  CINIT(FTP_USE_EPSV, LONG, 85),
+
+  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
+  CINIT(SSLCERTTYPE, OBJECTPOINT, 86),
+
+  /* name of the file keeping your private SSL-key */
+  CINIT(SSLKEY, OBJECTPOINT, 87),
+
+  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
+  CINIT(SSLKEYTYPE, OBJECTPOINT, 88),
+
+  /* crypto engine for the SSL-sub system */
+  CINIT(SSLENGINE, OBJECTPOINT, 89),
+
+  /* set the crypto engine for the SSL-sub system as default
+     the param has no meaning...
+   */
+  CINIT(SSLENGINE_DEFAULT, LONG, 90),
+
+  /* Non-zero value means to use the global dns cache */
+  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* To becomeO BSOLETE soon */
+
+  /* DNS cache timeout */
+  CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+
+  /* send linked-list of pre-transfer QUOTE commands (Wesley Laxton)*/
+  CINIT(PREQUOTE, OBJECTPOINT, 93),
+
+  /* set the debug function */
+  CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+
+  /* set the data for the debug function */
+  CINIT(DEBUGDATA, OBJECTPOINT, 95),
+
+  /* mark this as start of a cookie session */
+  CINIT(COOKIESESSION, LONG, 96),
+
+  /* The CApath directory used to validate the peer certificate
+     this option is used only if SSL_VERIFYPEER is true */
+  CINIT(CAPATH, OBJECTPOINT, 97),
+
+  /* Instruct libcurl to use a smaller receive buffer */
+  CINIT(BUFFERSIZE, LONG, 98),
+
+  /* Instruct libcurl to not use any signal/alarm handlers, even when using
+     timeouts. This option is useful for multi-threaded applications.
+     See libcurl-the-guide for more background information. */
+  CINIT(NOSIGNAL, LONG, 99),
+
+  /* Provide a CURLShare for mutexing non-ts data */
+  CINIT(SHARE, OBJECTPOINT, 100),
+
+  /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
+     CURLPROXY_SOCKS4 and CURLPROXY_SOCKS5. */
+  CINIT(PROXYTYPE, LONG, 101),
+
+  /* Set the Accept-Encoding string. Use this to tell a server you would like
+     the response to be compressed. */
+  CINIT(ENCODING, OBJECTPOINT, 102),
+
+  /* Set pointer to private data */
+  CINIT(PRIVATE, OBJECTPOINT, 103),
+
+  /* Set aliases for HTTP 200 in the HTTP Response header */
+  CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
+
+  /* Continue to send authentication (user+password) when following locations,
+     even when hostname changed. This can potentionally send off the name
+     and password to whatever host the server decides. */
+  CINIT(UNRESTRICTED_AUTH, LONG, 105),
+
+  /* Specificly switch on or off the FTP engine's use of the EPRT command ( it
+     also disables the LPRT attempt). By default, those ones will always be
+     attempted before the good old traditional PORT command. */
+  CINIT(FTP_USE_EPRT, LONG, 106),
+
+  /* Set this to a bitmask value to enable the particular authentications
+     methods you like. Use this in combination with CURLOPT_USERPWD.
+     Note that setting multiple bits may cause extra network round-trips. */
+  CINIT(HTTPAUTH, LONG, 107),
+
+  /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
+     in second argument. The function must be matching the
+     curl_ssl_ctx_callback proto. */
+  CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+
+  /* Set the userdata for the ssl context callback function's third
+     argument */
+  CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+
+  /* FTP Option that causes missing dirs to be created on the remote server */
+  CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+
+  /* Set this to a bitmask value to enable the particular authentications
+     methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+     Note that setting multiple bits may cause extra network round-trips. */
+  CINIT(PROXYAUTH, LONG, 111),
+
+  /* FTP option that changes the timeout, in seconds, associated with
+     getting a response.  This is different from transfer timeout time and
+     essentially places a demand on the FTP server to acknowledge commands
+     in a timely manner. */
+  CINIT(FTP_RESPONSE_TIMEOUT, LONG , 112),
+
+  /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
+     tell libcurl to resolve names to those IP versions only. This only has
+     affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
+  CINIT(IPRESOLVE, LONG, 113),
+
+  /* Set this option to limit the size of a file that will be downloaded from
+     an HTTP or FTP server.
+
+     Note there is also _LARGE version which adds large file support for
+     platforms which have larger off_t sizes.  See MAXFILESIZE_LARGE below. */
+  CINIT(MAXFILESIZE, LONG, 114),
+
+  /* See the comment for INFILESIZE above, but in short, specifies
+   * the size of the file being uploaded.  -1 means unknown.
+   */
+  CINIT(INFILESIZE_LARGE, OFF_T, 115),
+
+  /* Sets the continuation offset.  There is also a LONG version of this;
+   * look above for RESUME_FROM.
+   */
+  CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+
+  /* Sets the maximum size of data that will be downloaded from
+   * an HTTP or FTP server.  See MAXFILESIZE above for the LONG version.
+   */
+  CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+
+  /* Set this option to the file name of your .netrc file you want libcurl
+     to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
+     a poor attempt to find the user's home directory and check for a .netrc
+     file in there. */
+  CINIT(NETRC_FILE, OBJECTPOINT, 118),
+
+  /* Enable SSL/TLS for FTP, pick one of:
+     CURLFTPSSL_TRY     - try using SSL, proceed anyway otherwise
+     CURLFTPSSL_CONTROL - SSL for the control connection or fail
+     CURLFTPSSL_ALL     - SSL for all communication or fail
+  */
+  CINIT(FTP_SSL, LONG, 119),
+
+  /* The _LARGE version of the standard POSTFIELDSIZE option */
+  CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+
+  /* Enable/disable the TCP Nagle algorithm */
+  CINIT(TCP_NODELAY, LONG, 121),
+
+  /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+
+  /* When doing 3rd party transfer, set the source user and password with
+     this */
+  CINIT(SOURCE_USERPWD, OBJECTPOINT, 123),
+
+  /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+  /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
+
+  /* When doing 3rd party transfer, set the source pre-quote linked list
+     of commands with this */
+  CINIT(SOURCE_PREQUOTE, OBJECTPOINT, 127),
+
+  /* When doing 3rd party transfer, set the source post-quote linked list
+     of commands with this */
+  CINIT(SOURCE_POSTQUOTE, OBJECTPOINT, 128),
+
+  /* When FTP over SSL/TLS is selected (with CURLOPT_FTP_SSL), this option
+     can be used to change libcurl's default action which is to first try
+     "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
+     response has been received.
+
+     Available parameters are:
+     CURLFTPAUTH_DEFAULT - let libcurl decide
+     CURLFTPAUTH_SSL     - try "AUTH SSL" first, then TLS
+     CURLFTPAUTH_TLS     - try "AUTH TLS" first, then SSL
+  */
+  CINIT(FTPSSLAUTH, LONG, 129),
+
+  CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
+  CINIT(IOCTLDATA, OBJECTPOINT, 131),
+
+  /* To make a 3rd party transfer, set the source URL with this */
+  CINIT(SOURCE_URL, OBJECTPOINT, 132),
+
+  /* When doing 3rd party transfer, set the source quote linked list of
+     commands with this */
+  CINIT(SOURCE_QUOTE, OBJECTPOINT, 133),
+
+  /* zero terminated string for pass on to the FTP server when asked for
+     "account" info */
+  CINIT(FTP_ACCOUNT, OBJECTPOINT, 134),
+
+  /* feed cookies into cookie engine */
+  CINIT(COOKIELIST, OBJECTPOINT, 135),
+
+  /* ignore Content-Length */
+  CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+
+  /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
+     response. Typically used for FTP-SSL purposes but is not restricted to
+     that. libcurl will then instead use the same IP address it used for the
+     control connection. */
+  CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+
+  /* Select "file method" to use when doing FTP, see the curl_ftpmethod
+     above. */
+  CINIT(FTP_FILEMETHOD, LONG, 138),
+
+  /* Local port number to bind the socket to */
+  CINIT(LOCALPORT, LONG, 139),
+
+  /* Number of ports to try, including the first one set with LOCALPORT.
+     Thus, setting it to 1 will make no additional attempts but the first.
+  */
+  CINIT(LOCALPORTRANGE, LONG, 140),
+
+  /* no transfer, set up connection and let application use the socket by
+     extracting it with CURLINFO_LASTSOCKET */
+  CINIT(CONNECT_ONLY, LONG, 141),
+
+  /* Function that will be called to convert from the
+     network encoding (instead of using the iconv calls in libcurl) */
+  CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+
+  /* Function that will be called to convert to the
+     network encoding (instead of using the iconv calls in libcurl) */
+  CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+
+  /* Function that will be called to convert from UTF8
+     (instead of using the iconv calls in libcurl)
+     Note that this is used only for SSL certificate processing */
+  CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+
+  /* if the connection proceeds too quickly then need to slow it down */
+  /* limit-rate: maximum number of bytes per second to send or receive */
+  CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
+  CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+
+  /* Pointer to command string to send if USER/PASS fails. */
+  CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147),
+
+  CURLOPT_LASTENTRY /* the last unused */
+} CURLoption;
+
+  /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
+     name resolves addresses using more than one IP protocol version, this
+     option might be handy to force libcurl to use a specific IP version. */
+#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
+                                     versions that your system allows */
+#define CURL_IPRESOLVE_V4       1 /* resolve to ipv4 addresses */
+#define CURL_IPRESOLVE_V6       2 /* resolve to ipv6 addresses */
+
+  /* three convenient "aliases" that follow the name scheme better */
+#define CURLOPT_WRITEDATA CURLOPT_FILE
+#define CURLOPT_READDATA  CURLOPT_INFILE
+#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER
+
+#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
+                          the obsolete stuff removed! */
+#define CURLOPT_HTTPREQUEST    -1
+#define CURLOPT_FTPASCII       CURLOPT_TRANSFERTEXT
+#define CURLOPT_MUTE           -2
+#define CURLOPT_PASSWDFUNCTION -3
+#define CURLOPT_PASSWDDATA     -4
+#define CURLOPT_CLOSEFUNCTION  -5
+
+#define CURLOPT_SOURCE_HOST    -6
+#define CURLOPT_SOURCE_PATH    -7
+#define CURLOPT_SOURCE_PORT    -8
+#define CURLOPT_PASV_HOST      -9
+
+#else
+/* This is set if CURL_NO_OLDIES is defined at compile-time */
+#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
+#endif
+
+
+  /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
+enum {
+  CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
+                             like the library to choose the best possible
+                             for us! */
+  CURL_HTTP_VERSION_1_0,  /* please use HTTP 1.0 in the request */
+  CURL_HTTP_VERSION_1_1,  /* please use HTTP 1.1 in the request */
+
+  CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
+};
+
+  /* These enums are for use with the CURLOPT_NETRC option. */
+enum CURL_NETRC_OPTION {
+  CURL_NETRC_IGNORED,     /* The .netrc will never be read.
+                           * This is the default. */
+  CURL_NETRC_OPTIONAL,    /* A user:password in the URL will be preferred
+                           * to one in the .netrc. */
+  CURL_NETRC_REQUIRED,    /* A user:password in the URL will be ignored.
+                           * Unless one is set programmatically, the .netrc
+                           * will be queried. */
+  CURL_NETRC_LAST
+};
+
+enum {
+  CURL_SSLVERSION_DEFAULT,
+  CURL_SSLVERSION_TLSv1,
+  CURL_SSLVERSION_SSLv2,
+  CURL_SSLVERSION_SSLv3,
+
+  CURL_SSLVERSION_LAST /* never use, keep last */
+};
+
+
+typedef enum {
+  CURL_TIMECOND_NONE,
+
+  CURL_TIMECOND_IFMODSINCE,
+  CURL_TIMECOND_IFUNMODSINCE,
+  CURL_TIMECOND_LASTMOD,
+
+  CURL_TIMECOND_LAST
+} curl_TimeCond;
+
+#ifdef __BEOS__
+#include <support/SupportDefs.h>
+#endif
+
+
+/* curl_strequal() and curl_strnequal() are subject for removal in a future
+   libcurl, see lib/README.curlx for details */
+CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
+CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+
+/* name is uppercase CURLFORM_<name> */
+#ifdef CFINIT
+#undef CFINIT
+#endif
+
+#ifdef CURL_ISOCPP
+#define CFINIT(name) CURLFORM_ ## name
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define CFINIT(name) CURLFORM_/**/name
+#endif
+
+typedef enum {
+  CFINIT(NOTHING),        /********* the first one is unused ************/
+
+  /*  */
+  CFINIT(COPYNAME),
+  CFINIT(PTRNAME),
+  CFINIT(NAMELENGTH),
+  CFINIT(COPYCONTENTS),
+  CFINIT(PTRCONTENTS),
+  CFINIT(CONTENTSLENGTH),
+  CFINIT(FILECONTENT),
+  CFINIT(ARRAY),
+  CFINIT(OBSOLETE),
+  CFINIT(FILE),
+
+  CFINIT(BUFFER),
+  CFINIT(BUFFERPTR),
+  CFINIT(BUFFERLENGTH),
+
+  CFINIT(CONTENTTYPE),
+  CFINIT(CONTENTHEADER),
+  CFINIT(FILENAME),
+  CFINIT(END),
+  CFINIT(OBSOLETE2),
+
+  CURLFORM_LASTENTRY /* the last unusued */
+} CURLformoption;
+
+#undef CFINIT /* done */
+
+/* structure to be used as parameter for CURLFORM_ARRAY */
+struct curl_forms {
+  CURLformoption option;
+  const char     *value;
+};
+
+/* use this for multipart formpost building */
+/* Returns code for curl_formadd()
+ *
+ * Returns:
+ * CURL_FORMADD_OK             on success
+ * CURL_FORMADD_MEMORY         if the FormInfo allocation fails
+ * CURL_FORMADD_OPTION_TWICE   if one option is given twice for one Form
+ * CURL_FORMADD_NULL           if a null pointer was given for a char
+ * CURL_FORMADD_MEMORY         if the allocation of a FormInfo struct failed
+ * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
+ * CURL_FORMADD_INCOMPLETE     if the some FormInfo is not complete (or error)
+ * CURL_FORMADD_MEMORY         if a HttpPost struct cannot be allocated
+ * CURL_FORMADD_MEMORY         if some allocation for string copying failed.
+ * CURL_FORMADD_ILLEGAL_ARRAY  if an illegal option is used in an array
+ *
+ ***************************************************************************/
+typedef enum {
+  CURL_FORMADD_OK, /* first, no error */
+
+  CURL_FORMADD_MEMORY,
+  CURL_FORMADD_OPTION_TWICE,
+  CURL_FORMADD_NULL,
+  CURL_FORMADD_UNKNOWN_OPTION,
+  CURL_FORMADD_INCOMPLETE,
+  CURL_FORMADD_ILLEGAL_ARRAY,
+  CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
+
+  CURL_FORMADD_LAST /* last */
+} CURLFORMcode;
+
+/*
+ * NAME curl_formadd()
+ *
+ * DESCRIPTION
+ *
+ * Pretty advanved function for building multi-part formposts. Each invoke
+ * adds one part that together construct a full post. Then use
+ * CURLOPT_HTTPPOST to send it off to libcurl.
+ */
+CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
+                                      struct curl_httppost **last_post,
+                                      ...);
+
+/*
+ * callback function for curl_formget()
+ * The void *arg pointer will be the one passed as second argument to curl_formget().
+ * The character buffer passed to it must not be freed.
+ * Should return the buffer length passed to it as the argument "len" on success.
+ */
+typedef size_t (*curl_formget_callback)(void *arg, const char *buf, size_t len);
+
+/*
+ * NAME curl_formget()
+ *
+ * DESCRIPTION
+ *
+ * Serialize a curl_httppost struct built with curl_formadd().
+ * Accepts a void pointer as second argument which will be passed to
+ * the curl_formget_callback function.
+ * Returns 0 on success.
+ */
+CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
+                             curl_formget_callback append);
+/*
+ * NAME curl_formfree()
+ *
+ * DESCRIPTION
+ *
+ * Free a multipart formpost previously built with curl_formadd().
+ */
+CURL_EXTERN void curl_formfree(struct curl_httppost *form);
+
+/*
+ * NAME curl_getenv()
+ *
+ * DESCRIPTION
+ *
+ * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
+ * complete. DEPRECATED - see lib/README.curlx
+ */
+CURL_EXTERN char *curl_getenv(const char *variable);
+
+/*
+ * NAME curl_version()
+ *
+ * DESCRIPTION
+ *
+ * Returns a static ascii string of the libcurl version.
+ */
+CURL_EXTERN char *curl_version(void);
+
+/*
+ * NAME curl_easy_escape()
+ *
+ * DESCRIPTION
+ *
+ * Escapes URL strings (converts all letters consider illegal in URLs to their
+ * %XX versions). This function returns a new allocated string or NULL if an
+ * error occurred.
+ */
+CURL_EXTERN char *curl_easy_escape(CURL *handle,
+                                   const char *string,
+                                   int length);
+
+/* the previous version: */
+CURL_EXTERN char *curl_escape(const char *string,
+                              int length);
+
+
+/*
+ * NAME curl_easy_unescape()
+ *
+ * DESCRIPTION
+ *
+ * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
+ * versions). This function returns a new allocated string or NULL if an error
+ * occurred.
+ * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
+ * converted into the host encoding.
+ */
+CURL_EXTERN char *curl_easy_unescape(CURL *handle,
+                                     const char *string,
+                                     int length,
+                                     int *outlength);
+
+/* the previous version */
+CURL_EXTERN char *curl_unescape(const char *string,
+                                int length);
+
+/*
+ * NAME curl_free()
+ *
+ * DESCRIPTION
+ *
+ * Provided for de-allocation in the same translation unit that did the
+ * allocation. Added in libcurl 7.10
+ */
+CURL_EXTERN void curl_free(void *p);
+
+/*
+ * NAME curl_global_init()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() should be invoked exactly once for each application that
+ * uses libcurl
+ */
+CURL_EXTERN CURLcode curl_global_init(long flags);
+
+/*
+ * NAME curl_global_init_mem()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_init() or curl_global_init_mem() should be invoked exactly once
+ * for each application that uses libcurl.  This function can be used to
+ * initialize libcurl and set user defined memory management callback
+ * functions.  Users can implement memory management routines to check for
+ * memory leaks, check for mis-use of the curl library etc.  User registered
+ * callback routines with be invoked by this library instead of the system
+ * memory management routines like malloc, free etc.
+ */
+CURL_EXTERN CURLcode curl_global_init_mem(long flags,
+                                          curl_malloc_callback m,
+                                          curl_free_callback f,
+                                          curl_realloc_callback r,
+                                          curl_strdup_callback s,
+                                          curl_calloc_callback c);
+
+/*
+ * NAME curl_global_cleanup()
+ *
+ * DESCRIPTION
+ *
+ * curl_global_cleanup() should be invoked exactly once for each application
+ * that uses libcurl
+ */
+CURL_EXTERN void curl_global_cleanup(void);
+
+/* linked-list structure for the CURLOPT_QUOTE option (and other) */
+struct curl_slist {
+  char *data;
+  struct curl_slist *next;
+};
+
+/*
+ * NAME curl_slist_append()
+ *
+ * DESCRIPTION
+ *
+ * Appends a string to a linked list. If no list exists, it will be created
+ * first. Returns the new list, after appending.
+ */
+CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
+                                                 const char *);
+
+/*
+ * NAME curl_slist_free_all()
+ *
+ * DESCRIPTION
+ *
+ * free a previously built curl_slist.
+ */
+CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
+
+/*
+ * NAME curl_getdate()
+ *
+ * DESCRIPTION
+ *
+ * Returns the time, in seconds since 1 Jan 1970 of the time string given in
+ * the first argument. The time argument in the second parameter is unused
+ * and should be set to NULL.
+ */
+CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
+
+#define CURLINFO_STRING   0x100000
+#define CURLINFO_LONG     0x200000
+#define CURLINFO_DOUBLE   0x300000
+#define CURLINFO_SLIST    0x400000
+#define CURLINFO_MASK     0x0fffff
+#define CURLINFO_TYPEMASK 0xf00000
+
+typedef enum {
+  CURLINFO_NONE, /* first, never use this */
+  CURLINFO_EFFECTIVE_URL    = CURLINFO_STRING + 1,
+  CURLINFO_RESPONSE_CODE    = CURLINFO_LONG   + 2,
+  CURLINFO_TOTAL_TIME       = CURLINFO_DOUBLE + 3,
+  CURLINFO_NAMELOOKUP_TIME  = CURLINFO_DOUBLE + 4,
+  CURLINFO_CONNECT_TIME     = CURLINFO_DOUBLE + 5,
+  CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
+  CURLINFO_SIZE_UPLOAD      = CURLINFO_DOUBLE + 7,
+  CURLINFO_SIZE_DOWNLOAD    = CURLINFO_DOUBLE + 8,
+  CURLINFO_SPEED_DOWNLOAD   = CURLINFO_DOUBLE + 9,
+  CURLINFO_SPEED_UPLOAD     = CURLINFO_DOUBLE + 10,
+  CURLINFO_HEADER_SIZE      = CURLINFO_LONG   + 11,
+  CURLINFO_REQUEST_SIZE     = CURLINFO_LONG   + 12,
+  CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG   + 13,
+  CURLINFO_FILETIME         = CURLINFO_LONG   + 14,
+  CURLINFO_CONTENT_LENGTH_DOWNLOAD   = CURLINFO_DOUBLE + 15,
+  CURLINFO_CONTENT_LENGTH_UPLOAD     = CURLINFO_DOUBLE + 16,
+  CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
+  CURLINFO_CONTENT_TYPE     = CURLINFO_STRING + 18,
+  CURLINFO_REDIRECT_TIME    = CURLINFO_DOUBLE + 19,
+  CURLINFO_REDIRECT_COUNT   = CURLINFO_LONG   + 20,
+  CURLINFO_PRIVATE          = CURLINFO_STRING + 21,
+  CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG   + 22,
+  CURLINFO_HTTPAUTH_AVAIL   = CURLINFO_LONG   + 23,
+  CURLINFO_PROXYAUTH_AVAIL  = CURLINFO_LONG   + 24,
+  CURLINFO_OS_ERRNO         = CURLINFO_LONG   + 25,
+  CURLINFO_NUM_CONNECTS     = CURLINFO_LONG   + 26,
+  CURLINFO_SSL_ENGINES      = CURLINFO_SLIST  + 27,
+  CURLINFO_COOKIELIST       = CURLINFO_SLIST  + 28,
+  CURLINFO_LASTSOCKET       = CURLINFO_LONG   + 29,
+  CURLINFO_FTP_ENTRY_PATH   = CURLINFO_STRING + 30,
+  /* Fill in new entries below here! */
+
+  CURLINFO_LASTONE          = 30
+} CURLINFO;
+
+/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+   CURLINFO_HTTP_CODE */
+#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
+
+typedef enum {
+  CURLCLOSEPOLICY_NONE, /* first, never use this */
+
+  CURLCLOSEPOLICY_OLDEST,
+  CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
+  CURLCLOSEPOLICY_LEAST_TRAFFIC,
+  CURLCLOSEPOLICY_SLOWEST,
+  CURLCLOSEPOLICY_CALLBACK,
+
+  CURLCLOSEPOLICY_LAST /* last, never use this */
+} curl_closepolicy;
+
+#define CURL_GLOBAL_SSL (1<<0)
+#define CURL_GLOBAL_WIN32 (1<<1)
+#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
+#define CURL_GLOBAL_NOTHING 0
+#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
+
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different data locks for a single share */
+typedef enum {
+  CURL_LOCK_DATA_NONE = 0,
+  /*  CURL_LOCK_DATA_SHARE is used internaly to say that
+   *  the locking is just made to change the internal state of the share
+   *  itself.
+   */
+  CURL_LOCK_DATA_SHARE,
+  CURL_LOCK_DATA_COOKIE,
+  CURL_LOCK_DATA_DNS,
+  CURL_LOCK_DATA_SSL_SESSION,
+  CURL_LOCK_DATA_CONNECT,
+  CURL_LOCK_DATA_LAST
+} curl_lock_data;
+
+/* Different lock access types */
+typedef enum {
+  CURL_LOCK_ACCESS_NONE = 0,   /* unspecified action */
+  CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
+  CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
+  CURL_LOCK_ACCESS_LAST        /* never use */
+} curl_lock_access;
+
+typedef void (*curl_lock_function)(CURL *handle,
+                                   curl_lock_data data,
+                                   curl_lock_access locktype,
+                                   void *userptr);
+typedef void (*curl_unlock_function)(CURL *handle,
+                                     curl_lock_data data,
+                                     void *userptr);
+
+typedef void CURLSH;
+
+typedef enum {
+  CURLSHE_OK,  /* all is fine */
+  CURLSHE_BAD_OPTION, /* 1 */
+  CURLSHE_IN_USE,     /* 2 */
+  CURLSHE_INVALID,    /* 3 */
+  CURLSHE_NOMEM,      /* out of memory */
+  CURLSHE_LAST /* never use */
+} CURLSHcode;
+
+typedef enum {
+  CURLSHOPT_NONE,  /* don't use */
+  CURLSHOPT_SHARE,   /* specify a data type to share */
+  CURLSHOPT_UNSHARE, /* specify shich data type to stop sharing */
+  CURLSHOPT_LOCKFUNC,   /* pass in a 'curl_lock_function' pointer */
+  CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
+  CURLSHOPT_USERDATA,   /* pass in a user data pointer used in the lock/unlock
+                           callback functions */
+  CURLSHOPT_LAST  /* never use */
+} CURLSHoption;
+
+CURL_EXTERN CURLSH *curl_share_init(void);
+CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
+CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
+
+/****************************************************************************
+ * Structures for querying information about the curl library at runtime.
+ */
+
+typedef enum {
+  CURLVERSION_FIRST,
+  CURLVERSION_SECOND,
+  CURLVERSION_THIRD,
+  CURLVERSION_LAST /* never actually use this */
+} CURLversion;
+
+/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
+   basicly all programs ever, that want to get version information. It is
+   meant to be a built-in version number for what kind of struct the caller
+   expects. If the struct ever changes, we redefine the NOW to another enum
+   from above. */
+#define CURLVERSION_NOW CURLVERSION_THIRD
+
+typedef struct {
+  CURLversion age;          /* age of the returned struct */
+  const char *version;      /* LIBCURL_VERSION */
+  unsigned int version_num; /* LIBCURL_VERSION_NUM */
+  const char *host;         /* OS/host/cpu/machine when configured */
+  int features;             /* bitmask, see defines below */
+  const char *ssl_version;  /* human readable string */
+  long ssl_version_num;     /* not used anymore, always 0 */
+  const char *libz_version; /* human readable string */
+  /* protocols is terminated by an entry with a NULL protoname */
+  const char * const *protocols;
+
+  /* The fields below this were added in CURLVERSION_SECOND */
+  const char *ares;
+  int ares_num;
+
+  /* This field was added in CURLVERSION_THIRD */
+  const char *libidn;
+
+  /* Same as '_libiconv_version' if built with HAVE_ICONV */
+  int iconv_ver_num;
+} curl_version_info_data;
+
+#define CURL_VERSION_IPV6      (1<<0)  /* IPv6-enabled */
+#define CURL_VERSION_KERBEROS4 (1<<1)  /* kerberos auth is supported */
+#define CURL_VERSION_SSL       (1<<2)  /* SSL options are present */
+#define CURL_VERSION_LIBZ      (1<<3)  /* libz features are present */
+#define CURL_VERSION_NTLM      (1<<4)  /* NTLM auth is supported */
+#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */
+#define CURL_VERSION_DEBUG     (1<<6)  /* built with debug capabilities */
+#define CURL_VERSION_ASYNCHDNS (1<<7)  /* asynchronous dns resolves */
+#define CURL_VERSION_SPNEGO    (1<<8)  /* SPNEGO auth */
+#define CURL_VERSION_LARGEFILE (1<<9)  /* supports files bigger than 2GB */
+#define CURL_VERSION_IDN       (1<<10) /* International Domain Names support */
+#define CURL_VERSION_SSPI      (1<<11) /* SSPI is supported */
+#define CURL_VERSION_CONV      (1<<12) /* character conversions are
+                                          supported */
+
+/*
+ * NAME curl_version_info()
+ *
+ * DESCRIPTION
+ *
+ * This function returns a pointer to a static copy of the version info
+ * struct. See above.
+ */
+CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
+
+/*
+ * NAME curl_easy_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_easy_strerror function may be used to turn a CURLcode value
+ * into the equivalent human readable error string.  This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_easy_strerror(CURLcode);
+
+/*
+ * NAME curl_share_strerror()
+ *
+ * DESCRIPTION
+ *
+ * The curl_share_strerror function may be used to turn a CURLSHcode value
+ * into the equivalent human readable error string.  This is useful
+ * for printing meaningful error messages.
+ */
+CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
+
+#ifdef  __cplusplus
+}
+#endif
+
+/* unfortunately, the easy.h and multi.h include files need options and info
+  stuff before they can be included! */
+#include "easy.h" /* nothing in curl is fun without the easy stuff */
+#include "multi.h"
+
+#endif /* __CURL_CURL_H */

Added: trunk/code/libcurl/curl/curlver.h
===================================================================
--- trunk/code/libcurl/curl/curlver.h	                        (rev 0)
+++ trunk/code/libcurl/curl/curlver.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,56 @@
+#ifndef __CURL_CURLVER_H
+#define __CURL_CURLVER_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute 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: curlver.h,v 1.21 2006-06-12 07:24:14 bagder Exp $
+ ***************************************************************************/
+
+/* 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.15.5"
+
+/* The numeric version number is also available "in parts" by using these
+   defines: */
+#define LIBCURL_VERSION_MAJOR 7
+#define LIBCURL_VERSION_MINOR 15
+#define LIBCURL_VERSION_PATCH 5
+
+/* 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 (using 8 bits each). All three numbers are always represented
+   using two digits.  1.2 would appear as "0x010200" while version 9.11.7
+   appears as "0x090b07".
+
+   This 6-digit (24 bits) hexadecimal number does not show pre-release number,
+   and it is always a greater number in a more recent release. It makes
+   comparisons with greater than and less than work.
+*/
+#define LIBCURL_VERSION_NUM 0x070f05
+
+#endif /* __CURL_CURLVER_H */

Added: trunk/code/libcurl/curl/easy.h
===================================================================
--- trunk/code/libcurl/curl/easy.h	                        (rev 0)
+++ trunk/code/libcurl/curl/easy.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,81 @@
+#ifndef __CURL_EASY_H
+#define __CURL_EASY_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute 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: easy.h,v 1.13 2004/11/09 14:02:58 giva Exp $
+ ***************************************************************************/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+CURL_EXTERN CURL *curl_easy_init(void);
+CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
+CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
+CURL_EXTERN void curl_easy_cleanup(CURL *curl);
+
+/*
+ * NAME curl_easy_getinfo()
+ *
+ * DESCRIPTION
+ *
+ * Request internal information from the curl session with this function.  The
+ * third argument MUST be a pointer to a long, a pointer to a char * or a
+ * pointer to a double (as the documentation describes elsewhere).  The data
+ * pointed to will be filled in accordingly and can be relied upon only if the
+ * function returns CURLE_OK.  This function is intended to get used *AFTER* a
+ * performed transfer, all results from this function are undefined until the
+ * transfer is completed.
+ */
+CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
+
+
+/*
+ * NAME curl_easy_duphandle()
+ *
+ * DESCRIPTION
+ *
+ * Creates a new curl session handle with the same options set for the handle
+ * passed in. Duplicating a handle could only be a matter of cloning data and
+ * options, internal state info and things like persistant connections cannot
+ * be transfered. It is useful in multithreaded applications when you can run
+ * curl_easy_duphandle() for each new thread to avoid a series of identical
+ * curl_easy_setopt() invokes in every thread.
+ */
+CURL_EXTERN 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.
+ */
+CURL_EXTERN void curl_easy_reset(CURL *curl);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

Added: trunk/code/libcurl/curl/mprintf.h
===================================================================
--- trunk/code/libcurl/curl/mprintf.h	                        (rev 0)
+++ trunk/code/libcurl/curl/mprintf.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,62 @@
+#ifndef __CURL_MPRINTF_H
+#define __CURL_MPRINTF_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute 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: mprintf.h,v 1.13 2006-03-28 10:08:54 bagder Exp $
+ ***************************************************************************/
+
+#include <stdarg.h>
+#include <stdio.h> /* needed for FILE */
+
+#include "curl.h"
+
+CURL_EXTERN int curl_mprintf(const char *format, ...);
+CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
+CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
+CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...);
+CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
+CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
+CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
+CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, va_list args);
+CURL_EXTERN char *curl_maprintf(const char *format, ...);
+CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
+
+#ifdef _MPRINTF_REPLACE
+# define printf curl_mprintf
+# define fprintf curl_mfprintf
+#ifdef CURLDEBUG
+/* When built with CURLDEBUG we define away the sprintf() functions since we
+   don't want internal code to be using them */
+# define sprintf sprintf_was_used
+# define vsprintf vsprintf_was_used
+#else
+# define sprintf curl_msprintf
+# define vsprintf curl_mvsprintf
+#endif
+# define snprintf curl_msnprintf
+# define vprintf curl_mvprintf
+# define vfprintf curl_mvfprintf
+# define vsnprintf curl_mvsnprintf
+# define aprintf curl_maprintf
+# define vaprintf curl_mvaprintf
+#endif
+
+#endif /* __CURL_MPRINTF_H */

Added: trunk/code/libcurl/curl/multi.h
===================================================================
--- trunk/code/libcurl/curl/multi.h	                        (rev 0)
+++ trunk/code/libcurl/curl/multi.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,344 @@
+#ifndef __CURL_MULTI_H
+#define __CURL_MULTI_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute 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: multi.h,v 1.38 2006-08-04 18:53:48 danf Exp $
+ ***************************************************************************/
+/*
+  This is an "external" header file. Don't give away any internals here!
+
+  GOALS
+
+  o Enable a "pull" interface. The application that uses libcurl decides where
+    and when to ask libcurl to get/send data.
+
+  o Enable multiple simultaneous transfers in the same thread without making it
+    complicated for the application.
+
+  o Enable the application to select() on its own file descriptors and curl's
+    file descriptors simultaneous easily.
+
+*/
+#if defined(_WIN32) && !defined(WIN32)
+/* Chris Lewis mentioned that he doesn't get WIN32 defined, only _WIN32 so we
+   make this adjustment to catch this. */
+#define WIN32 1
+#endif
+
+#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__GNUC__) && \
+  !defined(__CYGWIN__) || defined(__MINGW32__)
+#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H))
+/* The check above prevents the winsock2 inclusion if winsock.h already was
+   included, since they can't co-exist without problems */
+#include <winsock2.h>
+#endif
+#else
+
+/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
+   libc5-based Linux systems. Only include it on system that are known to
+   require it! */
+#if defined(_AIX) || defined(NETWARE) || defined(__NetBSD__) || defined(_MINIX)
+#include <sys/select.h>
+#endif
+
+#ifndef _WIN32_WCE
+#include <sys/socket.h>
+#endif
+#include <sys/time.h>
+#include <sys/types.h>
+#endif
+
+/*
+ * This header file should not really need to include "curl.h" since curl.h
+ * itself includes this file and we expect user applications to do #include
+ * <curl/curl.h> without the need for especially including multi.h.
+ *
+ * For some reason we added this include here at one point, and rather than to
+ * break existing (wrongly written) libcurl applications, we leave it as-is
+ * but with this warning attached.
+ */
+#include "curl.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+typedef void CURLM;
+
+#ifndef curl_socket_typedef
+/* Public socket typedef */
+#ifdef WIN32
+typedef SOCKET curl_socket_t;
+#define CURL_SOCKET_BAD INVALID_SOCKET
+#else
+typedef int curl_socket_t;
+#define CURL_SOCKET_BAD -1
+#endif
+#define curl_socket_typedef
+#endif /* curl_socket_typedef */
+
+typedef enum {
+  CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
+                                    curl_multi_socket*() soon */
+  CURLM_OK,
+  CURLM_BAD_HANDLE,      /* the passed-in handle is not a valid CURLM handle */
+  CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
+  CURLM_OUT_OF_MEMORY,   /* if you ever get this, you're in deep sh*t */
+  CURLM_INTERNAL_ERROR,  /* this is a libcurl bug */
+  CURLM_BAD_SOCKET,      /* the passed in socket argument did not match */
+  CURLM_UNKNOWN_OPTION,  /* curl_multi_setopt() with unsupported option */
+  CURLM_LAST
+} CURLMcode;
+
+/* just to make code nicer when using curl_multi_socket() you can now check
+   for CURLM_CALL_MULTI_SOCKET too in the same style it works for
+   curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
+#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
+
+typedef enum {
+  CURLMSG_NONE, /* first, not used */
+  CURLMSG_DONE, /* This easy handle has completed. 'result' contains
+                   the CURLcode of the transfer */
+  CURLMSG_LAST /* last, not used */
+} CURLMSG;
+
+struct CURLMsg {
+  CURLMSG msg;       /* what this message means */
+  CURL *easy_handle; /* the handle it concerns */
+  union {
+    void *whatever;    /* message-specific data */
+    CURLcode result;   /* return code for transfer */
+  } data;
+};
+typedef struct CURLMsg CURLMsg;
+
+/*
+ * Name:    curl_multi_init()
+ *
+ * Desc:    inititalize multi-style curl usage
+ *
+ * Returns: a new CURLM handle to use in all 'curl_multi' functions.
+ */
+CURL_EXTERN CURLM *curl_multi_init(void);
+
+/*
+ * Name:    curl_multi_add_handle()
+ *
+ * Desc:    add a standard curl handle to the multi stack
+ *
+ * Returns: CURLMcode type, general multi error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
+                                            CURL *curl_handle);
+
+ /*
+  * Name:    curl_multi_remove_handle()
+  *
+  * Desc:    removes a curl handle from the multi stack again
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
+                                               CURL *curl_handle);
+
+ /*
+  * Name:    curl_multi_fdset()
+  *
+  * Desc:    Ask curl for its fd_set sets. The app can use these to select() or
+  *          poll() on. We want curl_multi_perform() called as soon as one of
+  *          them are ready.
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
+                                       fd_set *read_fd_set,
+                                       fd_set *write_fd_set,
+                                       fd_set *exc_fd_set,
+                                       int *max_fd);
+
+ /*
+  * Name:    curl_multi_perform()
+  *
+  * Desc:    When the app thinks there's data available for curl it calls this
+  *          function to read/write whatever there is right now. This returns
+  *          as soon as the reads and writes are done. This function does not
+  *          require that there actually is data available for reading or that
+  *          data can be written, it can be called just in case. It returns
+  *          the number of handles that still transfer data in the second
+  *          argument's integer-pointer.
+  *
+  * Returns: CURLMcode type, general multi error code. *NOTE* that this only
+  *          returns errors etc regarding the whole multi stack. There might
+  *          still have occurred problems on invidual transfers even when this
+  *          returns OK.
+  */
+CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
+                                         int *running_handles);
+
+ /*
+  * Name:    curl_multi_cleanup()
+  *
+  * Desc:    Cleans up and removes a whole multi stack. It does not free or
+  *          touch any individual easy handles in any way. We need to define
+  *          in what state those handles will be if this function is called
+  *          in the middle of a transfer.
+  *
+  * Returns: CURLMcode type, general multi error code.
+  */
+CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+
+/*
+ * Name:    curl_multi_info_read()
+ *
+ * Desc:    Ask the multi handle if there's any messages/informationals from
+ *          the individual transfers. Messages include informationals such as
+ *          error code from the transfer or just the fact that a transfer is
+ *          completed. More details on these should be written down as well.
+ *
+ *          Repeated calls to this function will return a new struct each
+ *          time, until a special "end of msgs" struct is returned as a signal
+ *          that there is no more to get at this point.
+ *
+ *          The data the returned pointer points to will not survive calling
+ *          curl_multi_cleanup().
+ *
+ *          The 'CURLMsg' struct is meant to be very simple and only contain
+ *          very basic informations. If more involved information is wanted,
+ *          we will provide the particular "transfer handle" in that struct
+ *          and that should/could/would be used in subsequent
+ *          curl_easy_getinfo() calls (or similar). The point being that we
+ *          must never expose complex structs to applications, as then we'll
+ *          undoubtably get backwards compatibility problems in the future.
+ *
+ * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
+ *          of structs. It also writes the number of messages left in the
+ *          queue (after this read) in the integer the second argument points
+ *          to.
+ */
+CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
+                                          int *msgs_in_queue);
+
+/*
+ * Name:    curl_multi_strerror()
+ *
+ * Desc:    The curl_multi_strerror function may be used to turn a CURLMcode
+ *          value into the equivalent human readable error string.  This is
+ *          useful for printing meaningful error messages.
+ *
+ * Returns: A pointer to a zero-terminated error message.
+ */
+CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
+
+/*
+ * Name:    curl_multi_socket() and
+ *          curl_multi_socket_all()
+ *
+ * Desc:    An alternative version of curl_multi_perform() that allows the
+ *          application to pass in one of the file descriptors that have been
+ *          detected to have "action" on them and let libcurl perform.
+ *          See man page for details.
+ */
+#define CURL_POLL_NONE   0
+#define CURL_POLL_IN     1
+#define CURL_POLL_OUT    2
+#define CURL_POLL_INOUT  3
+#define CURL_POLL_REMOVE 4
+
+#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
+
+typedef int (*curl_socket_callback)(CURL *easy,      /* easy handle */
+                                    curl_socket_t s, /* socket */
+                                    int what,        /* see above */
+                                    void *userp,     /* private callback
+                                                        pointer */
+                                    void *socketp);  /* private socket
+                                                        pointer */
+
+CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
+                                        int *running_handles);
+
+CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+                                            int *running_handles);
+
+/*
+ * Name:    curl_multi_timeout()
+ *
+ * Desc:    Returns the maximum number of milliseconds the app is allowed to
+ *          wait before curl_multi_socket() or curl_multi_perform() must be
+ *          called (to allow libcurl's timed events to take place).
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
+                                         long *milliseconds);
+
+#undef CINIT /* re-using the same name as in curl.h */
+
+#ifdef CURL_ISOCPP
+#define CINIT(name,type,number) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + number
+#else
+/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
+#define LONG          CURLOPTTYPE_LONG
+#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
+#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
+#define OFF_T         CURLOPTTYPE_OFF_T
+#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
+#endif
+
+typedef enum {
+  /* This is the socket callback function pointer */
+  CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+
+  /* This is the argument passed to the socket callback */
+  CINIT(SOCKETDATA, OBJECTPOINT, 2),
+
+  CURLMOPT_LASTENTRY /* the last unused */
+} CURLMoption;
+
+
+/*
+ * Name:    curl_multi_setopt()
+ *
+ * Desc:    Sets options for the multi handle.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
+                                        CURLMoption option, ...);
+
+
+/*
+ * Name:    curl_multi_assign()
+ *
+ * Desc:    This function sets an association in the multi handle between the
+ *          given socket and a private pointer of the application. This is
+ *          (only) useful for curl_multi_socket uses.
+ *
+ * Returns: CURLM error code.
+ */
+CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
+                                        curl_socket_t sockfd, void *sockp);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif

Added: trunk/code/libcurl/curl/stdcheaders.h
===================================================================
--- trunk/code/libcurl/curl/stdcheaders.h	                        (rev 0)
+++ trunk/code/libcurl/curl/stdcheaders.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1,34 @@
+#ifndef __STDC_HEADERS_H
+#define __STDC_HEADERS_H
+/***************************************************************************
+ *                                  _   _ ____  _     
+ *  Project                     ___| | | |  _ \| |    
+ *                             / __| | | | |_) | |    
+ *                            | (__| |_| |  _ <| |___ 
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
+ * 
+ * You may opt to use, copy, modify, merge, publish, distribute 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: stdcheaders.h,v 1.8 2004/01/07 09:19:34 bagder Exp $
+ ***************************************************************************/
+
+#include <sys/types.h>
+
+size_t fread (void *, size_t, size_t, FILE *);
+size_t fwrite (const void *, size_t, size_t, FILE *);
+
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size_t);
+
+#endif

Added: trunk/code/libcurl/curl/types.h
===================================================================
--- trunk/code/libcurl/curl/types.h	                        (rev 0)
+++ trunk/code/libcurl/curl/types.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -0,0 +1 @@
+/* not used */

Added: trunk/code/libs/win32/libcurl.a
===================================================================
(Binary files differ)


Property changes on: trunk/code/libs/win32/libcurl.a
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/code/qcommon/qcommon.h
===================================================================
--- trunk/code/qcommon/qcommon.h	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/code/qcommon/qcommon.h	2006-09-11 16:41:55 UTC (rev 898)
@@ -1100,4 +1100,10 @@
 #define	CL_ENCODE_START		12
 #define CL_DECODE_START		4
 
+// flags for sv_allowDownload and cl_allowDownload
+#define DLF_ENABLE 1
+#define DLF_NO_REDIRECT 2
+#define DLF_NO_UDP 4
+#define DLF_NO_DISCONNECT 8
+
 #endif // _QCOMMON_H_

Modified: trunk/code/server/sv_client.c
===================================================================
--- trunk/code/server/sv_client.c	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/code/server/sv_client.c	2006-09-11 16:41:55 UTC (rev 898)
@@ -801,7 +801,9 @@
 		}
 
 		// We open the file here
-		if ( !sv_allowDownload->integer || idPack || unreferenced ||
+		if ( !(sv_allowDownload->integer & DLF_ENABLE) ||
+			(sv_allowDownload->integer & DLF_NO_UDP) ||
+			idPack || unreferenced ||
 			( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) <= 0 ) {
 			// cannot auto-download file
 			if(unreferenced)
@@ -818,7 +820,10 @@
 				else {
 					Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload id pk3 file \"%s\"", cl->downloadName);
 				}
-			} else if ( !sv_allowDownload->integer ) {
+			}
+			else if ( !(sv_allowDownload->integer & DLF_ENABLE) ||
+				(sv_allowDownload->integer & DLF_NO_UDP) ) {
+
 				Com_Printf("clientDownload: %d : \"%s\" download disabled", cl - svs.clients, cl->downloadName);
 				if (sv_pure->integer) {
 					Com_sprintf(errorMessage, sizeof(errorMessage), "Could not download \"%s\" because autodownloading is disabled on the server.\n\n"

Modified: trunk/code/server/sv_init.c
===================================================================
--- trunk/code/server/sv_init.c	2006-09-07 14:14:30 UTC (rev 897)
+++ trunk/code/server/sv_init.c	2006-09-11 16:41:55 UTC (rev 898)
@@ -606,6 +606,7 @@
 	Cvar_Get ("nextmap", "", CVAR_TEMP );
 
 	sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO);
+	Cvar_Get ("sv_dlURL", "", CVAR_SERVERINFO | CVAR_ARCHIVE);
 	sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 );
 	sv_master[1] = Cvar_Get ("sv_master2", "", CVAR_ARCHIVE );
 	sv_master[2] = Cvar_Get ("sv_master3", "", CVAR_ARCHIVE );




More information about the quake3-commits mailing list