4 * Header file for the TclCurl extension to enable Tcl interpreters
7 * Copyright (c) 2001-2009 Andres Garcia Garcia.
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 #if (defined(WIN32) || defined(_WIN32))
15 #define CURL_STATICLIB 1
18 #include <curl/curl.h>
19 #include <curl/types.h>
20 #include <curl/easy.h>
26 #define _MPRINTF_REPLACE
27 #include <curl/mprintf.h>
34 * Windows needs to know which symbols to export. Unix does not.
35 * BUILD_tclcurl should be undefined for Unix.
36 * Actually I don't use this, but it was in TEA so I keep in case
37 * I ever understand what it is for.
41 #undef TCL_STORAGE_CLASS
42 #define TCL_STORAGE_CLASS DLLEXPORT
45 #define TclCurlVersion "7.19.6"
48 * This struct will contain the data of a transfer if the user wants
49 * to put the body into a Tcl variable
57 * Struct that will be used for a linked list with all the
60 struct formArrayStruct {
61 struct curl_forms *formArray;
62 struct curl_slist *formHeaderList;
63 struct formArrayStruct *next;
69 Tcl_Command shareToken;
71 struct curl_slist *headerList;
72 struct curl_slist *quote;
73 struct curl_slist *prequote;
74 struct curl_slist *postquote;
75 struct curl_httppost *postListFirst;
76 struct curl_httppost *postListLast;
77 struct formArrayStruct *formArray;
87 char *errorBufferName;
98 struct MemoryStruct bodyVar;
100 char *cancelTransVarName;
105 struct curl_slist *http200aliases;
108 char *sshkeycallProc;
111 struct shcurlObjData {
118 CONST static char *commandTable[] = {
131 CONST static char *optionTable[] = {
132 "CURLOPT_URL", "CURLOPT_FILE", "CURLOPT_INFILE",
133 "CURLOPT_USERAGENT", "CURLOPT_REFERER", "CURLOPT_VERBOSE",
134 "CURLOPT_HEADER", "CURLOPT_NOBODY", "CURLOPT_PROXY",
135 "CURLOPT_PROXYPORT", "CURLOPT_HTTPPROXYTUNNEL", "CURLOPT_FAILONERROR",
136 "CURLOPT_TIMEOUT", "CURLOPT_LOW_SPEED_LIMIT", "CURLOPT_LOW_SPEED_TIME",
137 "CURLOPT_RESUME_FROM", "CURLOPT_INFILESIZE", "CURLOPT_UPLOAD",
138 "CURLOPT_FTPLISTONLY", "CURLOPT_FTPAPPEND", "CURLOPT_NETRC",
139 "CURLOPT_FOLLOWLOCATION","CURLOPT_TRANSFERTEXT", "CURLOPT_PUT",
140 "CURLOPT_MUTE", "CURLOPT_USERPWD", "CURLOPT_PROXYUSERPWD",
141 "CURLOPT_RANGE", "CURLOPT_ERRORBUFFER", "CURLOPT_HTTPGET",
142 "CURLOPT_POST", "CURLOPT_POSTFIELDS", "CURLOPT_POSTFIELDSIZE",
143 "CURLOPT_FTPPORT", "CURLOPT_COOKIE", "CURLOPT_COOKIEFILE",
144 "CURLOPT_HTTPHEADER", "CURLOPT_HTTPPOST", "CURLOPT_SSLCERT",
145 "CURLOPT_SSLCERTPASSWD", "CURLOPT_SSLVERSION", "CURLOPT_CRLF",
146 "CURLOPT_QUOTE", "CURLOPT_POSTQUOTE", "CURLOPT_WRITEHEADER",
147 "CURLOPT_TIMECONDITION", "CURLOPT_TIMEVALUE", "CURLOPT_CUSTOMREQUEST",
148 "CURLOPT_STDERR", "CURLOPT_INTERFACE", "CURLOPT_KRB4LEVEL",
149 "CURLOPT_SSL_VERIFYPEER","CURLOPT_CAINFO", "CURLOPT_FILETIME",
150 "CURLOPT_MAXREDIRS", "CURLOPT_MAXCONNECTS", "CURLOPT_CLOSEPOLICY",
151 "CURLOPT_RANDOM_FILE", "CURLOPT_EGDSOCKET", "CURLOPT_CONNECTTIMEOUT",
152 "CURLOPT_NOPROGRESS", "CURLOPT_HEADERVAR", "CURLOPT_BODYVAR",
153 "CURLOPT_PROGRESSPROC","CURLOPT_CANCELTRANSVARNAME","CURLOPT_WRITEPROC",
154 "CURLOPT_READPROC", "CURLOPT_SSL_VERIFYHOST", "CURLOPT_COOKIEJAR",
155 "CURLOPT_SSL_CIPHER_LIST","CURLOPT_HTTP_VERSION", "CURLOPT_FTP_USE_EPSV",
156 "CURLOPT_SSLCERTTYPE", "CURLOPT_SSLKEY", "CURLOPT_SSLKEYTYPE",
157 "CURLOPT_SSLKEYPASSWD", "CURLOPT_SSL_ENGINE", "CURLOPT_SSL_ENGINEDEFAULT",
158 "CURLOPT_PREQUOTE", "CURLOPT_DEBUGPROC", "CURLOPT_DNS_CACHE_TIMEOUT",
159 "CURLOPT_DNS_USE_GLOBAL_CACHE", "CURLOPT_COOKIESESSION","CURLOPT_CAPATH",
160 "CURLOPT_BUFFERSIZE", "CURLOPT_NOSIGNAL", "CURLOPT_ENCODING",
161 "CURLOPT_PROXYTYPE", "CURLOPT_HTTP200ALIASES", "CURLOPT_UNRESTRICTED_AUTH",
162 "CURLOPT_FTP_USE_EPRT", "CURLOPT_NOSUCHOPTION", "CURLOPT_HTTPAUTH",
163 "CURLOPT_FTP_CREATE_MISSING_DIRS", "CURLOPT_PROXYAUTH",
164 "CURLOPT_FTP_RESPONSE_TIMEOUT", "CURLOPT_IPRESOLVE",
165 "CURLOPT_MAXFILESIZE", "CURLOPT_NETRC_FILE", "CURLOPT_FTP_SSL",
166 "CURLOPT_SHARE", "CURLOPT_PORT", "CURLOPT_TCP_NODELAY",
167 "CURLOPT_AUTOREFERER", "CURLOPT_SOURCE_HOST", "CURLOPT_SOURCE_USERPWD",
168 "CURLOPT_SOURCE_PATH", "CURLOPT_SOURCE_PORT", "CURLOPT_PASV_HOST",
169 "CURLOPT_SOURCE_PREQUOTE","CURLOPT_SOURCE_POSTQUOTE",
170 "CURLOPT_FTPSSLAUTH", "CURLOPT_SOURCE_URL", "CURLOPT_SOURCE_QUOTE",
171 "CURLOPT_FTP_ACCOUNT", "CURLOPT_IGNORE_CONTENT_LENGTH",
172 "CURLOPT_COOKIELIST", "CURLOPT_FTP_SKIP_PASV_IP",
173 "CURLOPT_FTP_FILEMETHOD", "CURLOPT_LOCALPORT", "CURLOPT_LOCALPORTRANGE",
174 "CURLOPT_MAX_SEND_SPEED_LARGE", "CURLOPT_MAX_RECV_SPEED_LARGE",
175 "CURLOPT_FTP_ALTERNATIVE_TO_USER", "CURLOPT_SSL_SESSIONID_CACHE",
176 "CURLOPT_SSH_AUTH_TYPES", "CURLOPT_SSH_PUBLIC_KEYFILE",
177 "CURLOPT_SSH_PRIVATE_KEYFILE", "CURLOPT_TIMEOUT_MS",
178 "CURLOPT_CONNECTTIMEOUT_MS", "CURLOPT_HTTP_CONTENT_DECODING",
179 "CURLOPT_HTTP_TRANSFER_DECODING", "CURLOPT_KRBLEVEL",
180 "CURLOPT_NEW_FILE_PERMS", "CURLOPT_NEW_DIRECTORY_PERMS",
181 "CURLOPT_KEYPASSWD", "CURLOPT_APPEND", "CURLOPT_DIRLISTONLY",
182 "CURLOPT_USE_SSL", "CURLOPT_POST301", "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5",
183 "CURLOPT_PROXY_TRANSFER_MODE", "CURLOPT_CRLFILE",
184 "CURLOPT_ISSUERCERT", "CURLOPT_ADDRESS_SCOPE", "CURLOPT_CERTINFO",
185 "CURLOPT_POSTREDIR", "CURLOPT_USERNAME", "CURLOPT_PASSWORD",
186 "CURLOPT_PROXYUSERNAME", "CURLOPT_PROXYPASSWORD", "CURLOPT_TFTP_BLKSIZE",
187 "CURLOPT_SOCKS5_GSSAPI_SERVICE", "CURLOPT_SOCKS5_GSSAPI_NEC",
188 "CURLOPT_PROTOCOLS", "CURLOPT_REDIR_PROTOCOLS","CURLOPT_FTP_SSL_CC",
189 "CURLOPT_SSH_KNOWNHOSTS", "CURLOPT_SSH_KEYFUNCTION",
193 CONST static char *configTable[] = {
194 "-url", "-file", "-infile",
195 "-useragent", "-referer", "-verbose",
196 "-header", "-nobody", "-proxy",
197 "-proxyport", "-httpproxytunnel", "-failonerror",
198 "-timeout", "-lowspeedlimit", "-lowspeedtime",
199 "-resumefrom", "-infilesize", "-upload",
200 "-ftplistonly", "-ftpappend", "-netrc",
201 "-followlocation", "-transfertext", "-put",
202 "-mute", "-userpwd", "-proxyuserpwd",
203 "-range", "-errorbuffer", "-httpget",
204 "-post", "-postfields", "-postfieldssize",
205 "-ftpport", "-cookie", "-cookiefile",
206 "-httpheader", "-httppost", "-sslcert",
207 "-sslcertpasswd", "-sslversion", "-crlf",
208 "-quote", "-postquote", "-writeheader",
209 "-timecondition", "-timevalue", "-customrequest",
210 "-stderr", "-interface", "-krb4level",
211 "-sslverifypeer", "-cainfo", "-filetime",
212 "-maxredirs", "-maxconnects", "-closepolicy",
213 "-randomfile", "-egdsocket", "-connecttimeout",
214 "-noprogress", "-headervar", "-bodyvar",
215 "-progressproc", "-canceltransvarname", "-writeproc",
216 "-readproc", "-sslverifyhost", "-cookiejar",
217 "-sslcipherlist", "-httpversion", "-ftpuseepsv",
218 "-sslcerttype", "-sslkey", "-sslkeytype",
219 "-sslkeypasswd", "-sslengine", "-sslenginedefault",
220 "-prequote", "-debugproc", "-dnscachetimeout",
221 "-dnsuseglobalcache", "-cookiesession", "-capath",
222 "-buffersize", "-nosignal", "-encoding",
223 "-proxytype", "-http200aliases", "-unrestrictedauth",
224 "-ftpuseeprt", "-command", "-httpauth",
225 "-ftpcreatemissingdirs", "-proxyauth",
226 "-ftpresponsetimeout", "-ipresolve",
227 "-maxfilesize", "-netrcfile", "-ftpssl",
228 "-share", "-port", "-tcpnodelay",
229 "-autoreferer", "-sourcehost", "-sourceuserpwd",
230 "-sourcepath", "-sourceport", "-pasvhost",
231 "-sourceprequote", "-sourcepostquote", "-ftpsslauth",
232 "-sourceurl", "-sourcequote", "-ftpaccount",
233 "-ignorecontentlength", "-cookielist",
234 "-ftpskippasvip", "-ftpfilemethod", "-localport",
236 "-maxsendspeed", "-maxrecvspeed",
237 "-ftpalternativetouser", "-sslsessionidcache",
238 "-sshauthtypes", "-sshpublickeyfile", "-sshprivatekeyfile",
239 "-timeoutms", "-connecttimeoutms", "-contentdecoding",
240 "-transferdecoding", "-krblevel", "-newfileperms",
241 "-newdirectoryperms", "-keypasswd", "-append",
242 "-dirlistonly", "-usessl", "-post301",
243 "-sshhostpublickeymd5", "-proxytransfermode",
244 "-crlfile", "-issuercert", "-addressscope",
245 "-certinfo", "-postredir", "-username",
246 "-password", "-proxyuser", "-proxypassword",
247 "-tftpblksize", "-socks5gssapiservice","-socks5gssapinec",
248 "-protocols", "-redirprotocols", "-ftpsslcc",
249 "-sshknownhosts", "-sshkeyproc",
253 CONST static char *timeCond[] = {
254 "ifmodsince", "ifunmodsince",
258 CONST static char *getInfoTable[]={
259 "effectiveurl", "httpcode", "responsecode",
260 "filetime", "totaltime", "namelookuptime",
261 "connecttime", "pretransfertime","sizeupload",
262 "sizedownload", "speeddownload", "speedupload",
263 "headersize", "requestsize", "sslverifyresult",
264 "contentlengthdownload", "contentlengthupload",
265 "starttransfertime", "contenttype",
266 "redirecttime", "redirectcount", "httpauthavail",
267 "proxyauthavail", "oserrno", "numconnects",
268 "sslengines", "httpconnectcode","cookielist",
269 "ftpentrypath", "redirecturl", "primaryip",
270 "appconnecttime", "certinfo", "conditionunmet",
274 CONST static char *curlFormTable[]={
275 "name", "contents", "file", "contenttype", "contentheader", "filename",
276 "bufferName", "buffer", "filecontent", (char *)NULL
279 CONST static char *httpVersionTable[] = {
280 "none", "1.0", "1.1", (char *)NULL
283 CONST static char *netrcTable[] = {
284 "optional", "ignored", "required", (char *)NULL
287 CONST static char *encodingTable[] = {
288 "identity", "deflated", "all", (char *)NULL
291 CONST static char *versionInfoTable[] = {
292 "-version", "-versionnum", "-host", "-features",
293 "-sslversion", "-sslversionnum", "-libzversion",
294 "-protocols", (char *)NULL
297 CONST static char *proxyTypeTable[] = {
298 "http", "socks4", "socks4a", "socks5", "socks5hostname", (char *)NULL
301 CONST static char *httpAuthMethods[] = {
302 "basic", "digest", "digestie", "gssnegotiate", "ntlm", "any", "anysafe", (char *)NULL
305 CONST static char *ipresolve[] = {
306 "whatever", "v4", "v6", (char *)NULL
309 CONST static char *ftpssl[] = {
310 "nope", "try", "control", "all", (char *)NULL
313 CONST static char *shareCmd[] = {
314 "share", "unshare", "cleanup", (char *)NULL
317 CONST static char *lockData[] = {
318 "cookies", "dns", (char *)NULL
321 CONST static char *ftpsslauth[] = {
322 "default", "ssl", "tls", (char *)NULL
325 CONST static char *ftpsslccc[] = {
326 "none", "passive", "active", (char *)NULL
329 CONST static char *sslversion[] = {
330 "default", "tlsv1", "sslv2", "sslv3", (char *)NULL
333 CONST static char *ftpfilemethod[] = {
334 "default", "multicwd", "nocwd", "singlecwd", (char *)NULL
337 CONST static char *sshauthtypes[] = {
338 "publickey", "password", "host", "keyboard", "any", (char *)NULL
341 CONST static char *postredir[] = {
342 "301", "302", "all", (char *)NULL
345 CONST static char *protocolNames[] = {
346 "http", "https", "ftp", "ftps", "scp", "sftp", "telnet", "ldap",
347 "ldaps","dict", "file","tftp", "all", (char*)NULL
350 static curlioerr curlseek(void *instream, curl_off_t offset, int origin);
352 int Tclcurl_MultiInit (Tcl_Interp *interp);
356 int Tclcurl_Init(Tcl_Interp *interp);
358 char *curlCreateObjCmd(Tcl_Interp *interp,struct curlObjData *curlData);
359 int curlInitObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,
360 Tcl_Obj *CONST objv[]);
361 int curlObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,
362 Tcl_Obj *CONST objv[]);
363 int curlDeleteCmd(ClientData clientData);
365 int curlPerform(Tcl_Interp *interp,CURL *curlHandle,struct curlObjData *curlData);
367 int curlSetOptsTransfer(Tcl_Interp *interp, struct curlObjData *curlData,int objc,
368 Tcl_Obj *CONST objv[]);
370 int curlConfigTransfer(Tcl_Interp *interp, struct curlObjData *curlData,int objc,
371 Tcl_Obj *CONST objv[]);
374 int curlDupHandle(Tcl_Interp *interp, struct curlObjData *curlData,int objc,
375 Tcl_Obj *CONST objv[]);
377 int curlResetHandle(Tcl_Interp *interp, struct curlObjData *curlData);
379 int curlSetOpts(Tcl_Interp *interp, struct curlObjData *curlData,
380 Tcl_Obj *CONST objv,int tableIndex);
382 int SetoptInt(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,
384 int SetoptLong(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,
386 int SetoptCurlOffT(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,
388 int SetoptChar(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,
389 int tableIndex,Tcl_Obj *tclObj);
390 int SetoptSHandle(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,
391 int tableIndex,Tcl_Obj *tclObj);
392 int SetoptsList(Tcl_Interp *interp,struct curl_slist **slistPtr,Tcl_Obj *CONST objv);
394 CURLcode curlGetInfo(Tcl_Interp *interp,CURL *curlHandle,int tableIndex);
396 void curlFreeSpace(struct curlObjData *curlData);
398 void curlErrorSetOpt(Tcl_Interp *interp,CONST char **configTable, int option,CONST char *parPtr);
400 size_t curlHeaderReader(void *ptr,size_t size,size_t nmemb,FILE *stream);
402 size_t curlBodyReader(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr);
404 int curlProgressCallback(void *clientp,double dltotal,double dlnow,
405 double ultotal,double ulnow);
407 size_t curlWriteProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr);
408 size_t curlReadProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr);
411 /* Puts a ssh key into a Tcl object */
412 Tcl_Obj *curlsshkeyextract(Tcl_Interp *interp,const struct curl_khkey *key);
414 /* Function that will be invoked by libcurl to see what the user wants to
415 do about the new ssh host */
416 size_t curlsshkeycallback(CURL *easy, /* easy handle */
417 const struct curl_khkey *knownkey, /* known */
418 const struct curl_khkey *foundkey, /* found */
419 enum curl_khmatch, /* libcurl's view on the keys */
422 int curlDebugProcInvoke(CURL *curlHandle, curl_infotype infoType,
423 unsigned char * dataPtr, size_t size, void *curlData);
425 int curlVersion (ClientData clientData, Tcl_Interp *interp,
426 int objc,Tcl_Obj *CONST objv[]);
428 int curlEscape(ClientData clientData, Tcl_Interp *interp,
429 int objc,Tcl_Obj *CONST objv[]);
431 int curlUnescape(ClientData clientData, Tcl_Interp *interp,
432 int objc,Tcl_Obj *CONST objv[]);
434 int curlVersionInfo (ClientData clientData, Tcl_Interp *interp,
435 int objc,Tcl_Obj *CONST objv[]);
437 int curlCopyCurlData (struct curlObjData *curlDataOld,
438 struct curlObjData *curlDataNew);
440 int curlOpenFile(Tcl_Interp *interp,char *fileName, FILE **handle, int writing, int text);
442 int curlOpenFiles (Tcl_Interp *interp,struct curlObjData *curlData);
443 void curlCloseFiles(struct curlObjData *curlData);
445 int curlSetPostData(Tcl_Interp *interp,struct curlObjData *curlData);
446 void curlResetPostData(struct curlObjData *curlDataPtr);
447 void curlResetFormArray(struct curl_forms *formArray);
449 void curlSetBodyVarName(Tcl_Interp *interp,struct curlObjData *curlDataPtr);
451 char *curlstrdup (char *old);
454 char *curlCreateShareObjCmd (Tcl_Interp *interp,struct shcurlObjData *shcurlData);
455 int curlShareInitObjCmd (ClientData clientData, Tcl_Interp *interp,
456 int objc,Tcl_Obj *CONST objv[]);
457 int curlShareObjCmd (ClientData clientData, Tcl_Interp *interp,
458 int objc,Tcl_Obj *CONST objv[]);
459 int curlCleanUpShareCmd(ClientData clientData);
462 TCL_DECLARE_MUTEX(cookieLock)
463 TCL_DECLARE_MUTEX(dnsLock)
464 TCL_DECLARE_MUTEX(sslLock)
465 TCL_DECLARE_MUTEX(connectLock)
467 void curlShareLockFunc (CURL *handle, curl_lock_data data
468 , curl_lock_access access, void *userptr);
469 void curlShareUnLockFunc(CURL *handle, curl_lock_data data, void *userptr);
472 int curlErrorStrings (Tcl_Interp *interp, Tcl_Obj *CONST objv,int type);
473 int curlEasyStringError (ClientData clientData, Tcl_Interp *interp,
474 int objc,Tcl_Obj *CONST objv[]);
475 int curlShareStringError (ClientData clientData, Tcl_Interp *interp,
476 int objc,Tcl_Obj *CONST objv[]);
477 int curlMultiStringError (ClientData clientData, Tcl_Interp *interp,
478 int objc,Tcl_Obj *CONST objv[]);