1 /*
2 * Copyright (c) 2001-2012 Mark Hessling <mark@rexx.org> All rights reserved.
3 *
4 * This program and the accompanying materials are made available under
5 * the terms of the Common Public License v1.0 which accompanies this
6 * distribution. A copy is also available at the following address:
7 * http://www.opensource.org/licenses/cpl1.0.php
8 */
9 /*
10 * For diffs between libcurl versions:
11 * http://upstream-tracker.org/versions/libcurl.html
12 */
13 /*
14 * Not implemented:
15 * setopt()
16 * CURLOPT_SEEKFUNCTION - 7.18.0
17 * CURLOPT_SEEKDATA - 7.18.0
18 * CURLOPT_SSH_KEYFUNCTION - 7.19.6
19 * CURLOPT_SSH_KEYDATA - 7.19.6
20 * CURLOPT_INTERLEAVEFUNCTION - 7.20.0
21 * CURLOPT_INTERLEAVEDATA - 7.20.0
22 * CURLOPT_CLOSESOCKETFUNCTION - 7.21.7
23 * CURLOPT_CLOSESOCKETDATA - 7.21.7
24 * curl_easy_pause() not implemented
25 *
26 * getopt()
27 * CURLINFO_CERTINFO - 7.19.1
28 */
29 /*
30 * CURLOPT options to add:
31 * 7.33.0 XOAUTH2_BEARER x x
32 * DNS_INTERFACE
33 * DNS_LOCAL_IP4
34 * DNS_LOCAL_IP6
35 * 7.34.0 LOGIN_OPTIONS x x
36 * 7.36.0 SSL_ENABLE_NPN
37 * SSL_ENABLE_ALPN
38 * EXPECT_100_TIMEOUT_MS
39 * 7.37.0 PROXYHEADER
40 * HEADEROPT
41 * 7.39.0 PINNEDPUBLICKEY
42 * 7.40.0 UNIX_SOCKET_PATH
43 * 7.41.0 SSL_VERIFYSTATUS x x
44 */
45
46 /*
47 * Error handling:
48 * error_rexxcurl error_curl
49 *
50 * ------------------------------------------------------------
51 * wrong # params ******* syntax error **********
52 * internal error set N/A
53 * cURL runtime errors -1 set
54 */
55 #pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
56
57 #ifdef HAVE_CONFIG_H
58 # include "config.h"
59 #else
60 # include "defines.h"
61 #endif
62
63 #if defined(__EMX__) && defined(USE_OS2REXX)
64 # define INCL_DOS
65 # define INCL_WIN
66 # define INCL_GPI
67 # include "rxpack.h"
68 # include "rexxcurl.h"
69 #else
70 # include "rexxcurl.h"
71 # include "rxpack.h"
72 #endif
73
74 char *RxPackageName = "rexxcurl";
75
76 #define LIBCURL_SUPPORTED_VERSION LIBCURL_VERSION_NUM
77
78 #define API_REXXCALLBACK_PRESENT 1
79 #define API_REXXCALLBACK_MISSING 0
80
81 #if defined(WIN32)
82 HMODULE handle=NULL;
83
84 typedef CURL * T_CURL_EASY_INIT(void);
85 T_CURL_EASY_INIT *p_curl_easy_init;
86
87 typedef CURLcode T_CURL_EASY_SETOPT(CURL *curl, CURLoption option, ...);
88 T_CURL_EASY_SETOPT *p_curl_easy_setopt;
89
90 typedef void T_CURL_EASY_RESET(CURL *curl );
91 T_CURL_EASY_RESET *p_curl_easy_reset;
92
93 typedef CURLcode T_CURL_EASY_PERFORM(CURL *curl);
94 T_CURL_EASY_PERFORM *p_curl_easy_perform;
95
96 typedef void T_CURL_EASY_CLEANUP(CURL *curl);
97 T_CURL_EASY_CLEANUP *p_curl_easy_cleanup;
98
99 typedef CURLcode T_CURL_EASY_GETINFO(CURL *curl, CURLINFO info, ...);
100 T_CURL_EASY_GETINFO *p_curl_easy_getinfo;
101
102 typedef CURLFORMcode T_CURL_FORMADD(struct curl_httppost **httppost, struct curl_httppost **last_post, ...);
103 T_CURL_FORMADD *p_curl_formadd;
104
105 typedef void T_CURL_FORMFREE(struct curl_httppost *form);
106 T_CURL_FORMFREE *p_curl_formfree;
107
108 typedef void T_CURL_GLOBAL_CLEANUP(void);
109 T_CURL_GLOBAL_CLEANUP *p_curl_global_cleanup;
110
111 typedef void T_CURL_GLOBAL_INIT(long flags);
112 T_CURL_GLOBAL_INIT *p_curl_global_init;
113
114 typedef struct curl_slist *T_CURL_SLIST_APPEND(struct curl_slist *, const char *);
115 T_CURL_SLIST_APPEND *p_curl_slist_append;
116
117 typedef void T_CURL_SLIST_FREE_ALL(struct curl_slist *);
118 T_CURL_SLIST_FREE_ALL *p_curl_slist_free_all;
119
120 typedef char *T_CURL_VERSION(void);
121 T_CURL_VERSION *p_curl_version;
122
123 typedef curl_version_info_data *T_CURL_VERSION_INFO(CURLversion);
124 T_CURL_VERSION_INFO *p_curl_version_info;
125
126 typedef char *T_CURL_EASY_ESCAPE(CURL *curl, char *url, int length);
127 T_CURL_EASY_ESCAPE *p_curl_easy_escape;
128
129 typedef void T_CURL_FREE(void *ptr);
130 T_CURL_FREE *p_curl_free;
131
132 typedef char *T_CURL_EASY_UNESCAPE(CURL *curl, char *url, int inlength, int *outlength);
133 T_CURL_EASY_UNESCAPE *p_curl_easy_unescape;
134
135 # define CURL_EASY_INIT ((*p_curl_easy_init))
136 # define CURL_EASY_SETOPT ((*p_curl_easy_setopt))
137 # define CURL_EASY_RESET ((*p_curl_easy_reset))
138 # define CURL_EASY_PERFORM ((*p_curl_easy_perform))
139 # define CURL_EASY_CLEANUP ((*p_curl_easy_cleanup))
140 # define CURL_EASY_GETINFO ((*p_curl_easy_getinfo))
141 # define CURL_FORMADD ((*p_curl_formadd))
142 # define CURL_FORMFREE ((*p_curl_formfree))
143 # define CURL_GLOBAL_INIT ((*p_curl_global_init))
144 # define CURL_GLOBAL_CLEANUP ((*p_curl_global_cleanup))
145 # define CURL_SLIST_APPEND ((*p_curl_slist_append))
146 # define CURL_SLIST_FREE_ALL ((*p_curl_slist_free_all))
147 # define CURL_VERSION ((*p_curl_version))
148 # define CURL_VERSION_INFO ((*p_curl_version_info))
149 # define CURL_EASY_ESCAPE ((*p_curl_easy_escape))
150 # define CURL_EASY_UNESCAPE ((*p_curl_easy_unescape))
151 # define CURL_FREE ((*p_curl_free))
152 #else
153 # define CURL_EASY_INIT curl_easy_init
154 # define CURL_EASY_SETOPT curl_easy_setopt
155 # define CURL_EASY_RESET curl_easy_reset
156 # define CURL_EASY_PERFORM curl_easy_perform
157 # define CURL_EASY_CLEANUP curl_easy_cleanup
158 # define CURL_EASY_GETINFO curl_easy_getinfo
159 # define CURL_FORMADD curl_formadd
160 # define CURL_FORMFREE curl_formfree
161 # define CURL_GLOBAL_INIT curl_global_init
162 # define CURL_GLOBAL_CLEANUP curl_global_cleanup
163 # define CURL_SLIST_APPEND curl_slist_append
164 # define CURL_SLIST_FREE_ALL curl_slist_free_all
165 # define CURL_VERSION curl_version
166 # define CURL_VERSION_INFO curl_version_info
167 # define CURL_EASY_ESCAPE curl_easy_escape
168 # define CURL_EASY_UNESCAPE curl_easy_unescape
169 # define CURL_FREE curl_free
170 #endif
171
172 #define INTERR_CURL_ERROR 1
173 #define INTERR_CURL_ERROR_STRING "Error from cURL"
174 #define INTERR_INVALID_NUMBER 2
175 #define INTERR_INVALID_NUMBER_STRING "Invalid Number"
176 #define INTERR_INVALID_OPTION 3
177 #define INTERR_INVALID_OPTION_STRING "Invalid Option"
178 #define INTERR_NO_MEMORY 4
179 #define INTERR_NO_MEMORY_STRING "Out of memory"
180 #define INTERR_INVALID_HANDLE 5
181 #define INTERR_INVALID_HANDLE_STRING "Invalid cURL handle"
182 #define INTERR_INVALID_FILE 6
183 #define INTERR_INVALID_FILE_STRING "Invalid filename"
184 #define INTERR_INVALID_BOOL 7
185 #define INTERR_INVALID_BOOL_STRING "Invalid boolean"
186 #define INTERR_INVALID_STEM 8
187 #define INTERR_INVALID_STEM_STRING "Expecting a stem as parameter"
188 #define INTERR_INVALID_VARIABLE 9
189 #define INTERR_INVALID_VARIABLE_STRING "Invalid variable:"
190 #define INTERR_READONLY_VARIABLE 10
191 #define INTERR_READONLY_VARIABLE_STRING "Cannot set readonly variable"
192 #define INTERR_TOO_FEW_ARGS 11
193 #define INTERR_TOO_FEW_ARGS_STRING "Too few arguments supplied"
194 #define INTERR_MANDATORY_FIELD 12
195 #define INTERR_MANDATORY_FIELD_STRING "Field must be specified"
196 #define INTERR_WRITING_TEMP_FILE 13
197 #define INTERR_WRITING_TEMP_FILE_STRING "Error writing to temporary file"
198 #define INTERR_STEM_VALUE 14
199 #define INTERR_STEM_VALUE_STRING "Stem values must be in form of name=value"
200
201 /*
202 * The following are option types for setopt()
203 * For those items that are not "basic" types, there is another
204 * table below which contains the definitions of the sub-options
205 */
206 #define RXCURLOPT_STRING 1 /* string */
207 #define RXCURLOPT_LIST 2 /* stem for slist */
208 #define RXCURLOPT_LONG 3 /* 32bit number */
209 #define RXCURLOPT_OUTFILE 4 /* output file */
210 #define RXCURLOPT_INFILE 5 /* input file - passed to cURL as FILE **/
211 #define RXCURLOPT_BOOL 6 /* bool */
212 #define RXCURLOPT_POLICY 7 /* policy */
213 #define RXCURLOPT_POST_DATA 8 /* stem for httppostdata */
214 #define RXCURLOPT_POST_FIELDS 9 /* stem for httppostfields */
215 #define RXCURLOPT_OUTSTEM 10 /* stem for outstem */
216 #define RXCURLOPT_HEADERSTEM 11 /* stem for headerstem */
217 #define RXCURLOPT_PROXYTYPE 12 /* proxytype */
218 #define RXCURLOPT_HTTP_VERSION 13 /* http_version */
219 #define RXCURLOPT_NETRC 14 /* netrc */
220 #define RXCURLOPT_TIMECOND 15 /* timecondition */
221 #define RXCURLOPT_IPRESOLVE 16 /* ipresolve */
222 #define RXCURLOPT_BITMAP 17 /* generic bitmap */
223 #define RXCURLOPT_BITMAP_AUTH 18 /* authorisation bitmap */
224 #define RXCURLOPT_LONGLONG 19 /* 64bit number */
225 #define RXCURLOPT_CALLBACK 20 /* libcurl callback */
226 #define RXCURLOPT_FTPSSL 21 /* ftp ssl */
227 #define RXCURLOPT_FTPSSLAUTH 22 /* ftp ssl auth */
228 #define RXCURLOPT_POST_FORM 23 /* option for processing after curl_formadd() calls */
229 #define RXCURLOPT_FTPSSLCCC 24 /* ftp ssl cc */
230 #define RXCURLOPT_INFILENAME 25 /* input file - validated as existing filename - passed to cURL as filename */
231 #define RXCURLOPT_BITMAP_SSHAUTH 26 /* SSH authorisation bitmap */
232 #define RXCURLOPT_FTP_CREATE_MISSING_DIRS 27 /* FTP create missing dirs */
233 #define RXCURLOPT_RTSP_REQUEST 28 /* RTSP Request options */
234 #define RXCURLOPT_PROTOCOLS 29 /* options for protocols */
235 #define RXCURLOPT_GSSAPI_DELEGATION 30 /* options for gssapi delegation */
236 #define RXCURLOPT_SSL_OPTIONS 31 /* options for SSL */
237 #define RXCURLOPT_BITMAP_REDIR 32 /* post redirection bitmap */
238 #define RXCURLOPT_BITMAP_TLSAUTH 33 /* TLS authorisation types */
239 #define RXCURLOPT_INSTEM 34 /* input stem - passed to cURL as FILE **/
240 #define RXCURLOPT_ERRFILE 35 /* error file */
241
242 #define RXCURLINFO_STRING 1 /* string */
243 #define RXCURLINFO_LONG 2 /* number */
244 #define RXCURLINFO_DOUBLE 3 /* double */
245 #define RXCURLINFO_LIST 4 /* stem for slist */
246 #define RXCURLINFO_CERTINFO 5 /* certinfo struct */
247 #define RXCURLINFO_BITMAP 6 /* bitmap input, word list output based on curlsetopt sub-options*/
248
249 static char *curl_errors[] =
250 {
251 "OK", /* 0 */
252 "UNSUPPORTED_PROTOCOL", /* 1 */
253 "FAILED_INIT", /* 2 */
254 "URL_MALFORMAT", /* 3 */
255 #if LIBCURL_VERSION_NUM >= 0x071505
256 "NOT_BUILT_IN", /* 4 */
257 #else
258 "URL_MALFORMAT_USER", /* 4 */
259 #endif
260 "COULDNT_RESOLVE_PROXY", /* 5 */
261 "COULDNT_RESOLVE_HOST", /* 6 */
262 "COULDNT_CONNECT", /* 7 */
263 "FTP_WEIRD_SERVER_REPLY", /* 8 */
264 "FTP_ACCESS_DENIED", /* 9 */
265 #if LIBCURL_VERSION_NUM >= 0x071800
266 "FTP_ACCEPT_FAILED", /* 10 */
267 #else
268 "FTP_USER_PASSWORD_INCORRECT", /* 10 */
269 #endif
270 "FTP_WEIRD_PASS_REPLY", /* 11 */
271 #if LIBCURL_VERSION_NUM >= 0x071800
272 "FTP_ACCEPT_TIMEOUT", /* 12 */
273 #else
274 "FTP_WEIRD_USER_REPLY", /* 12 */
275 #endif
276 "FTP_WEIRD_PASV_REPLY", /* 13 */
277 "FTP_WEIRD_227_FORMAT", /* 14 */
278 "FTP_CANT_GET_HOST", /* 15 */
279 "FTP_CANT_RECONNECT", /* 16 */
280 "FTP_COULDNT_SET_BINARY", /* 17 */
281 "PARTIAL_FILE", /* 18 */
282 "FTP_COULDNT_RETR_FILE", /* 19 */
283 "FTP_WRITE_ERROR", /* 20 */
284 "FTP_QUOTE_ERROR", /* 21 */
285 "HTTP_NOT_FOUND", /* 22 */
286 "WRITE_ERROR", /* 23 */
287 "MALFORMAT_USER", /* 24 - user name is illegally specified */
288 "FTP_COULDNT_STOR_FILE", /* 25 - failed FTP upload */
289 "READ_ERROR", /* 26 - could open/read from file */
290 "OUT_OF_MEMORY", /* 27 */
291 "OPERATION_TIMEOUTED", /* 28 - the timeout time was reached */
292 "FTP_COULDNT_SET_ASCII", /* 29 - TYPE A failed */
293 "FTP_PORT_FAILED", /* 30 - FTP PORT operation failed */
294 "FTP_COULDNT_USE_REST", /* 31 - the REST command failed */
295 "FTP_COULDNT_GET_SIZE", /* 32 - the SIZE command failed */
296 "HTTP_RANGE_ERROR", /* 33 - RANGE "command" didn"'t work */
297 "HTTP_POST_ERROR", /* 34 */
298 "SSL_CONNECT_ERROR", /* 35 - wrong when connecting with SSL */
299 "FTP_BAD_DOWNLOAD_RESUME", /* 36 - couldn"'t resume download */
300 "FILE_COULDNT_READ_FILE", /* 37 */
301 "LDAP_CANNOT_BIND", /* 38 */
302 "LDAP_SEARCH_FAILED", /* 39 */
303 "LIBRARY_NOT_FOUND", /* 40 */
304 "FUNCTION_NOT_FOUND", /* 41 */
305 "ABORTED_BY_CALLBACK", /* 42 */
306 "BAD_FUNCTION_ARGUMENT", /* 43 */
307 "BAD_CALLING_ORDER", /* 44 */
308 "HTTP_PORT_FAILED", /* 45 - HTTP Interface operation failed */
309 "BAD_PASSWORD_ENTERED", /* 46 - my_getpass() returns fail */
310 "TOO_MANY_REDIRECTS ", /* 47 - catch endless re-direct loops */
311 #if LIBCURL_VERSION_NUM >= 0x071505
312 "UNKNOWN_OPTION", /* 48 - User specified an unknown option */
313 #else
314 "UNKNOWN_TELNET_OPTION", /* 48 - User specified an unknown option */
315 #endif
316 "TELNET_OPTION_SYNTAX ", /* 49 - Malformed telnet option */
317 "OBSOLETE", /* 50 - removed after 7.7.3 */
318 "SSL_PEER_CERTIFICATE", /* 51 - peer"'s certificate wasn't ok */
319 "GOT_NOTHING", /* 52 - when this is a specific error */
320 "SSL_ENGINE_NOTFOUND", /* 53 - SSL crypto engine not found */
321 "SSL_ENGINE_SETFAILED", /* 54 - can not set SSL crypto engine as default */
322 "SEND_ERROR", /* 55 - failed sending network data */
323 "RECV_ERROR", /* 56 - failure in receiving network data */
324 "SHARE_IN_USE", /* 57 - share is in use */
325 "SSL_CERTPROBLEM", /* 58 - problem with the local certificate */
326 "SSL_CIPHER", /* 59 - couldn't use specified cipher */
327 "SSL_CACERT", /* 60 - problem with the CA cert (path?) */
328 "BAD_CONTENT_ENCODING", /* 61 - Unrecognized transfer encoding */
329 "LDAP_INVALID_URL", /* 62 - Invalid LDAP URL */
330 "FILESIZE_EXCEEDED", /* 63 - Maximum file size exceeded */
331 "USE_SSL_FAILED", /* 64 - Requested USE SSL level failed */
332 "SEND_FAIL_REWIND", /* 65 - When doing a send operation curl had to rewind the data to retransmit, but the rewinding operation failed */
333 "SSL_ENGINE_INITFAILED", /* 66 - Initiating the SSL Engine failed */
334 "LOGIN_DENIED", /* 67 - The remote server denied curl to login (Added in 7.13.1) */
335 "TFTP_NOTFOUND", /* 68 - file not found on server */
336 "TFTP_PERM", /* 69 - permission problem on server */
337 "TFTP_DISKFULL", /* 70 - out of disk space on server */
338 "TFTP_ILLEGAL", /* 71 - Illegal TFTP operation */
339 "TFTP_UNKNOWNID", /* 72 - Unknown transfer ID */
340 "TFTP_EXISTS", /* 73 - File already exists */
341 "TFTP_NOSUCHUSER", /* 74 - No such user */
342 "CONV_FAILED", /* 75 - conversion failed */
343 "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 */
344 "SSL_CACERT_BADFILE", /* 77 - could not load CACERT file, missing or wrong format */
345 "REMOTE_FILE_NOT_FOUND", /* 78 - remote file not found */
346 "SSH", /* 79 - error from the SSH layer, somewhat generic so the error message will be of interest when this has happened */
347 "SSL_SHUTDOWN_FAILED", /* 80 - Failed to shut down the SSL */
348 #if LIBCURL_VERSION_NUM >= 0x071202
349 "AGAIN", /* 81 - socket is not ready for send/recv, wait till it's ready and try again (Added in 7.18.2) */
350 #endif
351 #if LIBCURL_VERSION_NUM >= 0x071300
352 "SSL_CRL_BADFILE", /* 82 - could not load CRL file, missing or wrong format (Added in 7.19.0) */
353 "SSL_ISSUER_ERROR", /* 83 - Issuer check failed. (Added in 7.19.0) */
354 #endif
355 #if LIBCURL_VERSION_NUM >= 0x071400
356 "FTP_PRET_FAILED", /* 84 - a PRET command failed */
357 "RTSP_CSEQ_ERROR", /* 85 - mismatch of RTSP CSeq numbers */
358 "RTSP_SESSION_ERROR", /* 86 - mismatch of RTSP Session Identifiers */
359 #endif
360 #if LIBCURL_VERSION_NUM >= 0x071500
361 "FTP_BAD_FILE_LIST", /* 87 - unable to parse FTP file list */
362 "CHUNK_FAILED", /* 88 - chunk callback reported error */
363 #endif
364 NULL
365 };
366 static char *curl_formadd_errors[] =
367 {
368 "OK", /* 0 */
369 "MEMORY", /* 1 */
370 "OPTION_TWICE", /* 2 */
371 "NULL", /* 3 */
372 "UNKNOWN_OPTION", /* 4 */
373 "INCOMPLETE", /* 5 */
374 "ILLEGAL_ARRAY", /* 6 */
375 "DISABLED", /* 7 */
376 };
377
378 typedef struct
379 {
380 char *name;
381 unsigned long number;
382 int optiontype; /* things like STEM, STRING, INT */
383 char *newname; /* name of new value if this setting is deprecated, NULL means it is still valid */
384 } curl_options;
385
386 static curl_options RexxCurlOptions[] =
387 {
388 #if LIBCURL_VERSION_NUM >= 0x071506
389 { "ACCEPTENCODING" ,CURLOPT_ACCEPT_ENCODING ,RXCURLOPT_STRING , NULL },
390 #endif
391 #if LIBCURL_VERSION_NUM >= 0x071800
392 { "ACCEPTTIMEOUTMS" ,CURLOPT_ACCEPTTIMEOUT_MS,RXCURLOPT_LONG , NULL },
393 #endif
394 #if LIBCURL_VERSION_NUM >= 0x071300
395 { "ADDRESSSCOPE" ,CURLOPT_ADDRESS_SCOPE ,RXCURLOPT_LONG , NULL },
396 #endif
397 #if LIBCURL_VERSION_NUM >= 0x071100
398 { "APPEND" ,CURLOPT_APPEND ,RXCURLOPT_BOOL , NULL },
399 #endif
400 #if LIBCURL_VERSION_NUM >= 0x070a02
401 { "BUFFERSIZE" ,CURLOPT_BUFFERSIZE ,RXCURLOPT_LONG , NULL },
402 #endif
403 { "CAINFO" ,CURLOPT_CAINFO ,RXCURLOPT_INFILENAME , NULL },
404 #if LIBCURL_VERSION_NUM >= 0x070a02
405 { "CAPATH" ,CURLOPT_CAPATH ,RXCURLOPT_STRING , NULL },
406 #endif
407 #if LIBCURL_VERSION_NUM >= 0x071301
408 { "CERTINFO" ,CURLOPT_CERTINFO ,RXCURLOPT_LONG , NULL },
409 #endif
410 #if LIBCURL_VERSION_NUM < 0x072600
411 { "CLOSEPOLICY" ,CURLOPT_CLOSEPOLICY ,RXCURLOPT_POLICY , NULL },
412 #endif
413 #if LIBCURL_VERSION_NUM >= 0x070f02
414 { "CONNECTONLY" ,CURLOPT_CONNECT_ONLY ,RXCURLOPT_LONG , NULL },
415 #endif
416 { "CONNECTTIMEOUT" ,CURLOPT_CONNECTTIMEOUT ,RXCURLOPT_LONG , NULL },
417 #if LIBCURL_VERSION_NUM >= 0x071002
418 { "CONNECTTIMEOUTMS",CURLOPT_CONNECTTIMEOUT_MS ,RXCURLOPT_LONG , NULL },
419 #endif
420 { "COOKIE" ,CURLOPT_COOKIE ,RXCURLOPT_STRING , NULL },
421 { "COOKIEFILE" ,CURLOPT_COOKIEFILE ,RXCURLOPT_INFILENAME , NULL },
422 #if LIBCURL_VERSION_NUM >= 0x070900
423 { "COOKIEJAR" ,CURLOPT_COOKIEJAR ,RXCURLOPT_STRING , NULL },
424 #endif
425 #if LIBCURL_VERSION_NUM >= 0x070e01
426 { "COOKIELIST" ,CURLOPT_COOKIELIST ,RXCURLOPT_STRING , NULL },
427 #endif
428 #if LIBCURL_VERSION_NUM >= 0x070a02
429 { "COOKIESESSION" ,CURLOPT_COOKIESESSION ,RXCURLOPT_BOOL , NULL },
430 #endif
431 { "CRLF" ,CURLOPT_CRLF ,RXCURLOPT_BOOL , NULL },
432 #if LIBCURL_VERSION_NUM >= 0x071300
433 { "CRLFILE" ,CURLOPT_CRLFILE ,RXCURLOPT_STRING , NULL },
434 #endif
435 { "CUSTOMREQUEST" ,CURLOPT_CUSTOMREQUEST ,RXCURLOPT_STRING , NULL },
436 #if LIBCURL_VERSION_NUM >= 0x071100
437 { "DIRLISTONLY" ,CURLOPT_DIRLISTONLY ,RXCURLOPT_BOOL , NULL },
438 #endif
439 #if LIBCURL_VERSION_NUM >= 0x070a02
440 { "DNSCACHETIMEOUT" ,CURLOPT_DNS_CACHE_TIMEOUT,RXCURLOPT_LONG , NULL },
441 #if LIBCURL_VERSION_NUM >= 0x071800
442 { "DNSSERVERS" ,CURLOPT_DNS_SERVERS ,RXCURLOPT_STRING , NULL },
443 #endif
444 { "DNSUSEGLOBALCACHE",CURLOPT_DNS_USE_GLOBAL_CACHE,RXCURLOPT_BOOL , NULL },
445 #endif
446 { "EGDSOCKET" ,CURLOPT_EGDSOCKET ,RXCURLOPT_STRING , NULL },
447 #if LIBCURL_VERSION_NUM >= 0x070a02
448 # if LIBCURL_VERSION_NUM >= 0x071506
449 { "ENCODING" ,CURLOPT_ACCEPT_ENCODING ,RXCURLOPT_STRING , "ACCEPTENCODING" },
450 # else
451 { "ENCODING" ,CURLOPT_ENCODING ,RXCURLOPT_STRING , NULL },
452 # endif
453 #endif
454 { "ERRFILE" ,CURLOPT_STDERR ,RXCURLOPT_ERRFILE , NULL },
455 { "FAILONERROR" ,CURLOPT_FAILONERROR ,RXCURLOPT_BOOL , NULL },
456 { "FILETIME" ,CURLOPT_FILETIME ,RXCURLOPT_BOOL , NULL },
457 { "FOLLOWLOCATION" ,CURLOPT_FOLLOWLOCATION ,RXCURLOPT_BOOL , NULL },
458 { "FORBIDREUSE" ,CURLOPT_FORBID_REUSE ,RXCURLOPT_BOOL , NULL },
459 { "FRESHCONNECT" ,CURLOPT_FRESH_CONNECT ,RXCURLOPT_BOOL , NULL },
460 #if LIBCURL_VERSION_NUM >= 0x070e05
461 { "FTPALTERNATIVETOUSER", CURLOPT_FTP_ALTERNATIVE_TO_USER, RXCURLOPT_STRING , NULL },
462 #endif
463 #if LIBCURL_VERSION_NUM >= 0x071100
464 { "FTPAPPEND" ,CURLOPT_APPEND ,RXCURLOPT_BOOL , "APPEND" },
465 #else
466 { "FTPAPPEND" ,CURLOPT_FTPAPPEND ,RXCURLOPT_BOOL , NULL },
467 #endif
468 { "FTPCMDS" ,CURLOPT_QUOTE ,RXCURLOPT_LIST , NULL },
469 { "FTPCMDSAFTER" ,CURLOPT_POSTQUOTE ,RXCURLOPT_LIST , NULL },
470 { "FTPCMDSBEFORE" ,CURLOPT_PREQUOTE ,RXCURLOPT_LIST , NULL },
471 #if LIBCURL_VERSION_NUM >= 0x070a07
472 # if LIBCURL_VERSION_NUM >= 0x071304
473 { "FTPCREATEMISSINGDIRS", CURLOPT_FTP_CREATE_MISSING_DIRS, RXCURLOPT_FTP_CREATE_MISSING_DIRS , NULL },
474 # else
475 { "FTPCREATEMISSINGDIRS", CURLOPT_FTP_CREATE_MISSING_DIRS, RXCURLOPT_LONG , NULL },
476 # endif
477 #endif
478 { "FTPCRLF" ,CURLOPT_CRLF ,RXCURLOPT_BOOL , NULL },
479 #if LIBCURL_VERSION_NUM >= 0x071100
480 { "FTPLISTONLY" ,CURLOPT_DIRLISTONLY ,RXCURLOPT_BOOL , "DIRLISTONLY" },
481 #else
482 { "FTPLISTONLY" ,CURLOPT_FTPLISTONLY ,RXCURLOPT_BOOL , NULL },
483 #endif
484 { "FTPPORT" ,CURLOPT_FTPPORT ,RXCURLOPT_STRING , NULL },
485 #if LIBCURL_VERSION_NUM >= 0x070a08
486 { "FTPRESPONSETIMEOUT", CURLOPT_FTP_RESPONSE_TIMEOUT, RXCURLOPT_LONG, NULL },
487 #endif
488 #if LIBCURL_VERSION_NUM >= 0x070e00
489 { "FTPSKIPPASVIP" ,CURLOPT_FTP_SKIP_PASV_IP,RXCURLOPT_BOOL , NULL },
490 #endif
491 #if LIBCURL_VERSION_NUM >= 0x070b00
492 # if LIBCURL_VERSION_NUM >= 0x071100
493 { "FTPSSL" ,CURLOPT_USE_SSL ,RXCURLOPT_FTPSSL , "USESSL" },
494 # else
495 { "FTPSSL" ,CURLOPT_FTP_SSL ,RXCURLOPT_FTPSSL , NULL },
496 # endif
497 #endif
498 #if LIBCURL_VERSION_NUM >= 0x070c02
499 { "FTPSSLAUTH" ,CURLOPT_FTPSSLAUTH ,RXCURLOPT_FTPSSLAUTH , NULL },
500 #endif
501 #if LIBCURL_VERSION_NUM >= 0x071001
502 { "FTPSSLCCC" ,CURLOPT_FTP_SSL_CCC ,RXCURLOPT_FTPSSLCCC , NULL },
503 #endif
504 #if LIBCURL_VERSION_NUM >= 0x070a05
505 { "FTPUSEEPRT" ,CURLOPT_FTP_USE_EPRT ,RXCURLOPT_BOOL , NULL },
506 #endif
507 #if LIBCURL_VERSION_NUM >= 0x070a02
508 { "FTPUSEEPSV" ,CURLOPT_FTP_USE_EPSV ,RXCURLOPT_BOOL , NULL },
509 #endif
510 #if LIBCURL_VERSION_NUM >= 0x071400
511 { "FTPUSEPRET" ,CURLOPT_FTP_USE_PRET ,RXCURLOPT_BOOL , NULL },
512 #endif
513 #if LIBCURL_VERSION_NUM >= 0x071600
514 { "GSSAPIDELEGATION",CURLOPT_GSSAPI_DELEGATION,RXCURLOPT_GSSAPI_DELEGATION , NULL },
515 #endif
516 { "HEADER" ,CURLOPT_HEADER ,RXCURLOPT_BOOL , NULL },
517
518 #if LIBCURL_VERSION_NUM >= 0x072600
519 { "HEADERFILE" ,CURLOPT_HEADERDATA ,RXCURLOPT_OUTFILE , NULL },
520 { "HEADERSTEM" ,CURLOPT_HEADERDATA ,RXCURLOPT_HEADERSTEM , NULL },
521 #else
522 { "HEADERFILE" ,CURLOPT_WRITEHEADER ,RXCURLOPT_OUTFILE , NULL },
523 { "HEADERSTEM" ,CURLOPT_WRITEHEADER ,RXCURLOPT_HEADERSTEM , NULL },
524 #endif
525
526 #if LIBCURL_VERSION_NUM >= 0x070a03
527 { "HTTP200ALIASES" ,CURLOPT_HTTP200ALIASES ,RXCURLOPT_LIST , NULL },
528 #endif
529 #if LIBCURL_VERSION_NUM >= 0x070a06
530 { "HTTPAUTH" ,CURLOPT_HTTPAUTH ,RXCURLOPT_BITMAP_AUTH , NULL },
531 #endif
532 #if LIBCURL_VERSION_NUM >= 0x071002
533 { "HTTPCONTENTDECODING",CURLOPT_HTTP_CONTENT_DECODING,RXCURLOPT_BOOL , NULL },
534 #endif
535 #if LIBCURL_VERSION_NUM >= 0x070801
536 { "HTTPGET" ,CURLOPT_HTTPGET ,RXCURLOPT_BOOL , NULL },
537 #endif
538 { "HTTPHEADER" ,CURLOPT_HTTPHEADER ,RXCURLOPT_LIST , NULL },
539 { "HTTPPOST" ,CURLOPT_POST ,RXCURLOPT_BOOL , NULL },
540 { "HTTPPOSTDATA" ,CURLOPT_HTTPPOST ,RXCURLOPT_POST_DATA , NULL },
541 { "HTTPPOSTFIELDS" ,CURLOPT_POSTFIELDS ,RXCURLOPT_POST_FIELDS , NULL },
542 { "HTTPPOSTFORM" ,CURLOPT_HTTPPOST ,RXCURLOPT_POST_FORM , NULL },
543 { "HTTPPROXYTUNNEL" ,CURLOPT_HTTPPROXYTUNNEL ,RXCURLOPT_BOOL , NULL },
544 { "HTTPPUT" ,CURLOPT_PUT ,RXCURLOPT_BOOL , NULL },
545 #if LIBCURL_VERSION_NUM >= 0x071002
546 { "HTTPTRANSFERDECODING",CURLOPT_HTTP_TRANSFER_DECODING,RXCURLOPT_BOOL , NULL },
547 #endif
548 { "HTTPVERSION" ,CURLOPT_HTTP_VERSION ,RXCURLOPT_HTTP_VERSION, NULL },
549 #if LIBCURL_VERSION_NUM >= 0x070e01
550 { "IGNORECONTENTLENGTH",CURLOPT_IGNORE_CONTENT_LENGTH,RXCURLOPT_LONG, NULL },
551 #endif
552
553 #if LIBCURL_VERSION_NUM >= 0x072600
554 { "INFILE" ,CURLOPT_READDATA ,RXCURLOPT_INFILE , NULL },
555 { "INSTEM" ,CURLOPT_READDATA ,RXCURLOPT_INSTEM , NULL },
556 #else
557 { "INFILE" ,CURLOPT_INFILE ,RXCURLOPT_INFILE , NULL },
558 { "INSTEM" ,CURLOPT_INFILE ,RXCURLOPT_INSTEM , NULL },
559 #endif
560
561 { "INTERFACE" ,CURLOPT_INTERFACE ,RXCURLOPT_STRING , NULL },
562 #if LIBCURL_VERSION_NUM >= 0x070a08
563 { "IPRESOLVE" ,CURLOPT_IPRESOLVE ,RXCURLOPT_IPRESOLVE , NULL },
564 #endif
565 #if LIBCURL_VERSION_NUM >= 0x071300
566 { "ISSUERCERT" ,CURLOPT_ISSUERCERT ,RXCURLOPT_STRING , NULL },
567 #endif
568 #if LIBCURL_VERSION_NUM >= 0x071100
569 { "KEYPASSWD" ,CURLOPT_KEYPASSWD ,RXCURLOPT_STRING , NULL },
570 #endif
571 #if LIBCURL_VERSION_NUM >= 0x071100
572 { "KRB4LEVEL" ,CURLOPT_KRBLEVEL ,RXCURLOPT_STRING , "KRBLEVEL" },
573 { "KRBLEVEL" ,CURLOPT_KRBLEVEL ,RXCURLOPT_STRING , NULL },
574 #else
575 { "KRB4LEVEL" ,CURLOPT_KRB4LEVEL ,RXCURLOPT_STRING , NULL },
576 #endif
577 #if LIBCURL_VERSION_NUM >= 0x070f02
578 { "LOCALPORT" ,CURLOPT_LOCALPORT ,RXCURLOPT_LONG , NULL },
579 { "LOCALPORTRANGE" ,CURLOPT_LOCALPORTRANGE ,RXCURLOPT_LONG , NULL },
580 #endif
581 #if LIBCURL_VERSION_NUM >= 0x072200
582 { "LOGINOPTIONS" ,CURLOPT_LOGIN_OPTIONS ,RXCURLOPT_STRING , NULL },
583 #endif
584 { "LOWSPEEDLIMIT" ,CURLOPT_LOW_SPEED_LIMIT ,RXCURLOPT_LONG , NULL },
585 { "LOWSPEEDTIME" ,CURLOPT_LOW_SPEED_TIME ,RXCURLOPT_LONG , NULL },
586 #if LIBCURL_VERSION_NUM >= 0x071900
587 { "MAILAUTH" ,CURLOPT_MAIL_AUTH ,RXCURLOPT_STRING , NULL },
588 #endif
589 #if LIBCURL_VERSION_NUM >= 0x071400
590 { "MAILFROM" ,CURLOPT_MAIL_FROM ,RXCURLOPT_STRING , NULL },
591 { "MAILRCPT" ,CURLOPT_MAIL_RCPT ,RXCURLOPT_LIST , NULL },
592 #endif
593 { "MAXCONNECTS" ,CURLOPT_MAXCONNECTS ,RXCURLOPT_LONG , NULL },
594 #if LIBCURL_VERSION_NUM >= 0x070a08
595 { "MAXFILESIZE" ,CURLOPT_MAXFILESIZE ,RXCURLOPT_LONGLONG , NULL },
596 #endif
597 #if LIBCURL_VERSION_NUM >= 0x070e05
598 { "MAXRECVSPEEDLARGE", CURLOPT_MAX_RECV_SPEED_LARGE, RXCURLOPT_LONGLONG , NULL },
599 #endif
600 { "MAXREDIRS" ,CURLOPT_MAXREDIRS ,RXCURLOPT_LONG , NULL },
601 #if LIBCURL_VERSION_NUM >= 0x070e05
602 { "MAXSENDSPEEDLARGE", CURLOPT_MAX_SEND_SPEED_LARGE, RXCURLOPT_LONGLONG , NULL },
603 #endif
604 { "NETRC" ,CURLOPT_NETRC ,RXCURLOPT_NETRC , NULL },
605 #if LIBCURL_VERSION_NUM >= 0x070a09
606 { "NETRCFILE" ,CURLOPT_NETRC_FILE ,RXCURLOPT_INFILENAME , NULL },
607 #endif
608 #if LIBCURL_VERSION_NUM >= 0x071004
609 { "NEWDIRECTORYPERMS" ,CURLOPT_NEW_DIRECTORY_PERMS ,RXCURLOPT_LONG , NULL },
610 #endif
611 { "NOBODY" ,CURLOPT_NOBODY ,RXCURLOPT_BOOL , NULL },
612 #if LIBCURL_VERSION_NUM >= 0x070900
613 { "NOPROGRESS" ,CURLOPT_NOPROGRESS ,RXCURLOPT_BOOL , NULL },
614 #endif
615 #if LIBCURL_VERSION_NUM >= 0x071304
616 { "NOPROXY" ,CURLOPT_NOPROXY ,RXCURLOPT_STRING , NULL },
617 #endif
618 #if LIBCURL_VERSION_NUM >= 0x070a02
619 { "NOSIGNAL" ,CURLOPT_NOSIGNAL ,RXCURLOPT_BOOL , NULL },
620 #endif
621
622 #if LIBCURL_VERSION_NUM >= 0x072600
623 { "OUTFILE" ,CURLOPT_WRITEDATA ,RXCURLOPT_OUTFILE , NULL },
624 { "OUTSTEM" ,CURLOPT_WRITEDATA ,RXCURLOPT_OUTSTEM , NULL },
625 #else
626 { "OUTFILE" ,CURLOPT_FILE ,RXCURLOPT_OUTFILE , NULL },
627 { "OUTSTEM" ,CURLOPT_FILE ,RXCURLOPT_OUTSTEM , NULL },
628 #endif
629
630 #if LIBCURL_VERSION_NUM >= 0x071301
631 { "PASSWORD" ,CURLOPT_PASSWORD ,RXCURLOPT_STRING , NULL },
632 #endif
633 #if LIBCURL_VERSION_NUM >= 0x071101
634 # if LIBCURL_VERSION_NUM >= 0x071301
635 { "POST301" ,CURLOPT_POSTREDIR ,RXCURLOPT_BITMAP_REDIR, "POSTREDIR" },
636 # else
637 { "POST301" ,CURLOPT_POST301 ,RXCURLOPT_BOOL , NULL },
638 # endif
639 #endif
640
641 /* don't explicitly allow this as an option { "POSTFIELDSIZE" ,CURLOPT_POSTFIELDSIZE ,RXCURLOPT_LONG , NULL }, */
642
643 #if LIBCURL_VERSION_NUM >= 0x070a02
644 { "POSTQUOTE" ,CURLOPT_POSTQUOTE ,RXCURLOPT_LIST , NULL },
645 #endif
646 #if LIBCURL_VERSION_NUM >= 0x071301
647 { "POSTREDIR" ,CURLOPT_POSTREDIR ,RXCURLOPT_BITMAP_REDIR, NULL },
648 #endif
649 #if LIBCURL_VERSION_NUM >= 0x070a02
650 { "PREQUOTE" ,CURLOPT_PREQUOTE ,RXCURLOPT_LIST , NULL },
651 #endif
652 #if LIBCURL_VERSION_NUM >= 0x070a03
653 { "PRIVATE" ,CURLOPT_PRIVATE ,RXCURLOPT_STRING , NULL },
654 #endif
655 #if defined( REXXCALLBACK )
656 { "PROGRESSFUNCTION",CURLOPT_PROGRESSFUNCTION,RXCURLOPT_CALLBACK , NULL },
657 #endif
658 #if LIBCURL_VERSION_NUM >= 0x071304
659 { "PROTOCOLS" ,CURLOPT_PROTOCOLS ,RXCURLOPT_PROTOCOLS , NULL },
660 #endif
661 { "PROXY" ,CURLOPT_PROXY ,RXCURLOPT_STRING , NULL },
662 #if LIBCURL_VERSION_NUM >= 0x070a07
663 { "PROXYAUTH" ,CURLOPT_PROXYAUTH ,RXCURLOPT_BITMAP_AUTH , NULL },
664 #endif
665 #if LIBCURL_VERSION_NUM >= 0x071301
666 { "PROXYPASSWORD" ,CURLOPT_PROXYPASSWORD ,RXCURLOPT_STRING , NULL },
667 #endif
668 #if LIBCURL_VERSION_NUM >= 0x070900
669 { "PROXYPORT" ,CURLOPT_PROXYPORT ,RXCURLOPT_LONG , NULL },
670 #endif
671 #if LIBCURL_VERSION_NUM >= 0x071200
672 { "PROXYTRANSFERMODE",CURLOPT_PROXY_TRANSFER_MODE,RXCURLOPT_LONG , NULL },
673 #endif
674 #if LIBCURL_VERSION_NUM >= 0x070a02
675 { "PROXYTYPE" ,CURLOPT_PROXYTYPE ,RXCURLOPT_PROXYTYPE , NULL },
676 #endif
677 #if LIBCURL_VERSION_NUM >= 0x071301
678 { "PROXYUSERNAME" ,CURLOPT_PROXYUSERNAME ,RXCURLOPT_STRING , NULL },
679 #endif
680 { "PROXYUSERPWD" ,CURLOPT_PROXYUSERPWD ,RXCURLOPT_STRING , NULL },
681 #if LIBCURL_VERSION_NUM >= 0x070a02
682 { "QUOTE" ,CURLOPT_QUOTE ,RXCURLOPT_LIST , NULL },
683 #endif
684 { "RANDOMFILE" ,CURLOPT_RANDOM_FILE ,RXCURLOPT_STRING , NULL },
685 { "RANGE" ,CURLOPT_RANGE ,RXCURLOPT_STRING , NULL },
686 #if LIBCURL_VERSION_NUM >= 0x071304
687 { "REDIRPROTOCOLS" ,CURLOPT_REDIR_PROTOCOLS ,RXCURLOPT_PROTOCOLS , NULL },
688 #endif
689 { "REFERER" ,CURLOPT_REFERER ,RXCURLOPT_STRING , NULL },
690 #if LIBCURL_VERSION_NUM >= 0x071503
691 { "RESOLVE" ,CURLOPT_RESOLVE ,RXCURLOPT_LIST , NULL },
692 #endif
693 { "RESUMEFROM" ,CURLOPT_RESUME_FROM ,RXCURLOPT_LONGLONG , NULL },
694 #if LIBCURL_VERSION_NUM >= 0x071400
695 { "RTSPCLIENTCSEQ" ,CURLOPT_RTSP_CLIENT_CSEQ,RXCURLOPT_LONG , NULL },
696 { "RTSPHEADER" ,CURLOPT_RTSPHEADER ,RXCURLOPT_LIST , NULL },
697 { "RTSPREQUEST" ,CURLOPT_RTSP_REQUEST ,RXCURLOPT_RTSP_REQUEST, NULL },
698 { "RTSPSERVERCSEQ" ,CURLOPT_RTSP_SERVER_CSEQ,RXCURLOPT_LONG , NULL },
699 { "RTSPSESSIONID" ,CURLOPT_RTSP_SESSION_ID ,RXCURLOPT_STRING , NULL },
700 { "RTSPSTREAMURI" ,CURLOPT_RTSP_STREAM_URI ,RXCURLOPT_STRING , NULL },
701 { "RTSPTRANSPORT" ,CURLOPT_RTSP_TRANSPORT ,RXCURLOPT_STRING , NULL },
702 #endif
703 #if LIBCURL_VERSION_NUM >= 0x071304
704 { "SOCKS5GSSAPINEC" ,CURLOPT_SOCKS5_GSSAPI_NEC, RXCURLOPT_LONG , NULL },
705 { "SOCKS5GSSAPISERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE, RXCURLOPT_STRING , NULL },
706 #endif
707 #if LIBCURL_VERSION_NUM >= 0x070d00 && LIBCURL_VERSION_NUM < 0x071000
708 { "SOURCEPOSTQUOTE" ,CURLOPT_SOURCE_POSTQUOTE,RXCURLOPT_LIST , NULL },
709 { "SOURCEPREQUOTE" ,CURLOPT_SOURCE_PREQUOTE ,RXCURLOPT_LIST , NULL },
710 { "SOURCEQUOTE" ,CURLOPT_SOURCE_QUOTE ,RXCURLOPT_LIST , NULL },
711 { "SOURCEURL" ,CURLOPT_SOURCE_URL ,RXCURLOPT_STRING , NULL },
712 { "SOURCEUSERPWD" ,CURLOPT_SOURCE_USERPWD ,RXCURLOPT_STRING , NULL },
713 #endif
714 #if LIBCURL_VERSION_NUM >= 0x071001
715 { "SSHAUTHTYPES" ,CURLOPT_SSH_AUTH_TYPES ,RXCURLOPT_BITMAP_SSHAUTH , NULL },
716 #endif
717 #if LIBCURL_VERSION_NUM >= 0x071101
718 { "SSHHOSTPUBLICKEYMD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, RXCURLOPT_STRING , NULL },
719 #endif
720 #if LIBCURL_VERSION_NUM >= 0x071306
721 # if defined( REXXCALLBACK )
722 { "SSHKEYFUNCTION" ,CURLOPT_SSH_KEYFUNCTION, RXCURLOPT_CALLBACK , NULL },
723 # endif
724 { "SSHKNOWNHOSTS" ,CURLOPT_SSH_KNOWNHOSTS ,RXCURLOPT_STRING , NULL },
725 #endif
726 #if LIBCURL_VERSION_NUM >= 0x071001
727 { "SSHPRIVATEKEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE, RXCURLOPT_INFILENAME , NULL },
728 { "SSHPUBLICKEYFILE" , CURLOPT_SSH_PUBLIC_KEYFILE, RXCURLOPT_INFILENAME , NULL },
729 #endif
730 { "SSLCERT" ,CURLOPT_SSLCERT ,RXCURLOPT_STRING , NULL },
731 #if LIBCURL_VERSION_NUM >= 0x071100
732 { "SSLCERTPASSWD" ,CURLOPT_KEYPASSWD ,RXCURLOPT_STRING , "KEYPASSWD" },
733 #else
734 { "SSLCERTPASSWD" ,CURLOPT_SSLCERTPASSWD ,RXCURLOPT_STRING , NULL },
735 #endif
736 #if LIBCURL_VERSION_NUM >= 0x070a02
737 { "SSLCERTTYPE" ,CURLOPT_SSLCERTTYPE ,RXCURLOPT_STRING , NULL },
738 #endif
739 #if LIBCURL_VERSION_NUM >= 0x070900
740 { "SSLCIPHERLIST" ,CURLOPT_SSL_CIPHER_LIST ,RXCURLOPT_STRING , NULL },
741 #endif
742 #if LIBCURL_VERSION_NUM >= 0x070a02
743 { "SSLENGINE" ,CURLOPT_SSLENGINE ,RXCURLOPT_STRING , NULL },
744 { "SSLENGINEDEFAULT",CURLOPT_SSLENGINE_DEFAULT,RXCURLOPT_STRING , NULL },
745 { "SSLKEY" ,CURLOPT_SSLKEY ,RXCURLOPT_STRING , NULL },
746 # if LIBCURL_VERSION_NUM >= 0x071100
747 { "SSLKEYPASSWD" ,CURLOPT_KEYPASSWD ,RXCURLOPT_STRING , "KEYPASSWD" },
748 # else
749 { "SSLKEYPASSWD" ,CURLOPT_SSLKEYPASSWD ,RXCURLOPT_STRING , NULL },
750 # endif
751 { "SSLKEYTYPE" ,CURLOPT_SSLKEYTYPE ,RXCURLOPT_STRING , NULL },
752 #endif
753 #if LIBCURL_VERSION_NUM >= 0x071900
754 { "SSLOPTIONS" ,CURLOPT_SSL_OPTIONS ,RXCURLOPT_SSL_OPTIONS , NULL },
755 #endif
756 { "SSLPEERCERT" ,CURLOPT_CAINFO ,RXCURLOPT_STRING , NULL },
757 #if LIBCURL_VERSION_NUM >= 0x071000
758 { "SSLSESSIONIDCACHE", CURLOPT_SSL_SESSIONID_CACHE, RXCURLOPT_BOOL , NULL },
759 #endif
760 #if LIBCURL_VERSION_NUM >= 0x070801
761 { "SSLVERIFYHOST" ,CURLOPT_SSL_VERIFYHOST ,RXCURLOPT_LONG , NULL },
762 #endif
763 { "SSLVERIFYPEER" ,CURLOPT_SSL_VERIFYPEER ,RXCURLOPT_BOOL , NULL },
764 #if LIBCURL_VERSION_NUM >= 0x072A00
765 { "SSLVERIFYSTATUS" ,CURLOPT_SSL_VERIFYSTATUS,RXCURLOPT_BOOL , NULL },
766 #endif
767 { "SSLVERSION" ,CURLOPT_SSLVERSION ,RXCURLOPT_LONG , NULL },
768 #if LIBCURL_VERSION_NUM >= 0x071900
769 { "TCPKEEPALIVE" ,CURLOPT_TCP_KEEPALIVE ,RXCURLOPT_BOOL , NULL },
770 { "TCPKEEPIDLE" ,CURLOPT_TCP_KEEPIDLE ,RXCURLOPT_LONG , NULL },
771 { "TCPKEEPINTVL" ,CURLOPT_TCP_KEEPINTVL ,RXCURLOPT_LONG , NULL },
772 #endif
773 #if LIBCURL_VERSION_NUM >= 0x070d00
774 { "TCPNODELAY" ,CURLOPT_TCP_NODELAY ,RXCURLOPT_BOOL , NULL },
775 #endif
776 #if LIBCURL_VERSION_NUM >= 0x071304
777 { "TFTPBLKSIZE" ,CURLOPT_TFTP_BLKSIZE ,RXCURLOPT_LONG , NULL },
778 #endif
779 { "TIMECONDITION" ,CURLOPT_TIMECONDITION ,RXCURLOPT_TIMECOND , NULL },
780 { "TIMEOUT" ,CURLOPT_TIMEOUT ,RXCURLOPT_LONG , NULL },
781 #if LIBCURL_VERSION_NUM >= 0x071002
782 { "TIMEOUTMS" ,CURLOPT_TIMEOUT_MS ,RXCURLOPT_LONG , NULL },
783 #endif
784 { "TIMEVALUE" ,CURLOPT_TIMEVALUE ,RXCURLOPT_LONG , NULL },
785 #if LIBCURL_VERSION_NUM >= 0x071504
786 { "TLSAUTHPASSWORD" ,CURLOPT_TLSAUTH_PASSWORD,RXCURLOPT_STRING , NULL },
787 { "TLSAUTHTYPE" ,CURLOPT_TLSAUTH_TYPE ,RXCURLOPT_BITMAP_TLSAUTH, NULL },
788 { "TLSAUTHUSERNAME" ,CURLOPT_TLSAUTH_USERNAME,RXCURLOPT_STRING , NULL },
789 #endif
790 #if LIBCURL_VERSION_NUM >= 0x071506
791 { "TRANSFERENCODING",CURLOPT_TRANSFER_ENCODING,RXCURLOPT_BOOL , NULL },
792 #endif
793 { "TRANSFERTEXT" ,CURLOPT_TRANSFERTEXT ,RXCURLOPT_BOOL , NULL },
794 #if LIBCURL_VERSION_NUM >= 0x070908
795 { "UNRESTRICTEDAUTH",CURLOPT_UNRESTRICTED_AUTH ,RXCURLOPT_BOOL , NULL },
796 #endif
797 { "UPLOAD" ,CURLOPT_UPLOAD ,RXCURLOPT_BOOL , NULL },
798 { "URL" ,CURLOPT_URL ,RXCURLOPT_STRING , NULL },
799 { "USERAGENT" ,CURLOPT_USERAGENT ,RXCURLOPT_STRING , NULL },
800 #if LIBCURL_VERSION_NUM >= 0x071301
801 { "USERNAME" ,CURLOPT_USERNAME ,RXCURLOPT_STRING , NULL },
802 #endif
803 { "USERPWD" ,CURLOPT_USERPWD ,RXCURLOPT_STRING , NULL },
804 #if LIBCURL_VERSION_NUM >= 0x071100
805 { "USESSL" ,CURLOPT_USE_SSL ,RXCURLOPT_FTPSSL , NULL },
806 #endif
807 { "VERBOSE" ,CURLOPT_VERBOSE ,RXCURLOPT_BOOL , NULL },
808 #if LIBCURL_VERSION_NUM >= 0x071500
809 /* not implemented; need lots of callbacks */
810 /* { "WILDCARDMATCH" ,CURLOPT_WILDCARDMATCH ,RXCURLOPT_BOOL , NULL },*/
811 #endif
812 #if LIBCURL_VERSION_NUM >= 0x072100
813 { "XOAUTH2BEARER" ,CURLOPT_XOAUTH2_BEARER ,RXCURLOPT_STRING , NULL },
814 #endif
815 { NULL ,0 ,0 , NULL }
816 };
817
818 static curl_options RexxCurlGetinfos[] =
819 {
820 #if LIBCURL_VERSION_NUM >= 0x071300
821 { "APPCONNECT_TIME" ,CURLINFO_APPCONNECT_TIME ,RXCURLINFO_DOUBLE, NULL },
822 #endif
823 #if LIBCURL_VERSION_NUM >= 0x071301
824 { "CERTINFO" ,CURLINFO_CERTINFO ,RXCURLINFO_CERTINFO, NULL },
825 #endif
826 #if LIBCURL_VERSION_NUM >= 0x071304
827 { "CONDITION_UNMET" ,CURLINFO_CONDITION_UNMET ,RXCURLINFO_LONG , NULL },
828 #endif
829 { "CONNECT_TIME" ,CURLINFO_CONNECT_TIME ,RXCURLINFO_DOUBLE, NULL },
830 { "CONTENT_LENGTH_DOWNLOAD",CURLINFO_CONTENT_LENGTH_DOWNLOAD,RXCURLINFO_DOUBLE, NULL },
831 { "CONTENT_LENGTH_UPLOAD" ,CURLINFO_CONTENT_LENGTH_UPLOAD ,RXCURLINFO_DOUBLE, NULL },
832 #if LIBCURL_VERSION_NUM >= 0x070a02
833 { "CONTENT_TYPE" ,CURLINFO_CONTENT_TYPE ,RXCURLINFO_STRING, NULL },
834 #endif
835 #if LIBCURL_VERSION_NUM >= 0x070e01
836 { "COOKIELIST" ,CURLINFO_COOKIELIST ,RXCURLINFO_LIST , NULL },
837 #endif
838 { "EFFECTIVE_URL" ,CURLINFO_EFFECTIVE_URL ,RXCURLINFO_STRING, NULL },
839 { "FILE_TIME" ,CURLINFO_FILETIME ,RXCURLINFO_LONG , NULL },
840 #if LIBCURL_VERSION_NUM >= 0x070f04
841 { "FTP_ENTRY_PATH" ,CURLINFO_FTP_ENTRY_PATH ,RXCURLINFO_STRING, NULL },
842 #endif
843 { "HEADER_SIZE" ,CURLINFO_HEADER_SIZE ,RXCURLINFO_LONG , NULL },
844 #if LIBCURL_VERSION_NUM >= 0x070a08
845 { "HTTPAUTH_AVAIL" ,CURLINFO_HTTPAUTH_AVAIL ,RXCURLINFO_BITMAP, NULL },
846 #endif
847 #if LIBCURL_VERSION_NUM >= 0x070a07
848 { "HTTP_CODE" ,CURLINFO_RESPONSE_CODE ,RXCURLINFO_LONG , "RESPONSE_CODE" },
849 #else
850 { "HTTP_CODE" ,CURLINFO_HTTP_CODE ,RXCURLINFO_LONG , NULL },
851 #endif
852 { "HTTP_CONNECTCODE" ,CURLINFO_HTTP_CONNECTCODE ,RXCURLINFO_LONG , NULL },
853 #if LIBCURL_VERSION_NUM >= 0x070f02
854 { "LASTSOCKET" ,CURLINFO_LASTSOCKET ,RXCURLINFO_LONG , NULL },
855 #endif
856 #if LIBCURL_VERSION_NUM >= 0x071500
857 { "LOCAL_IP" ,CURLINFO_LOCAL_IP ,RXCURLINFO_STRING, NULL },
858 #endif
859 #if LIBCURL_VERSION_NUM >= 0x071500
860 { "LOCAL_PORT" ,CURLINFO_LOCAL_PORT ,RXCURLINFO_LONG , NULL },
861 #endif
862 { "NAMELOOKUP_TIME" ,CURLINFO_NAMELOOKUP_TIME ,RXCURLINFO_DOUBLE, NULL },
863 #if LIBCURL_VERSION_NUM >= 0x070c03
864 { "NUM_CONNECTS" ,CURLINFO_NUM_CONNECTS ,RXCURLINFO_LONG , NULL },
865 #endif
866 #if LIBCURL_VERSION_NUM >= 0x070c02
867 { "OS_ERRNO" ,CURLINFO_OS_ERRNO ,RXCURLINFO_LONG , NULL },
868 #endif
869 { "PRETRANSFER_TIME" ,CURLINFO_PRETRANSFER_TIME ,RXCURLINFO_DOUBLE, NULL },
870 #if LIBCURL_VERSION_NUM >= 0x071300
871 { "PRIMARY_IP" ,CURLINFO_PRIMARY_IP ,RXCURLINFO_STRING, NULL },
872 #endif
873 #if LIBCURL_VERSION_NUM >= 0x071500
874 { "PRIMARY_PORT" ,CURLINFO_PRIMARY_PORT ,RXCURLINFO_LONG , NULL },
875 #endif
876 #if LIBCURL_VERSION_NUM >= 0x070a03
877 { "PRIVATE" ,CURLINFO_PRIVATE ,RXCURLINFO_STRING, NULL },
878 #endif
879 #if LIBCURL_VERSION_NUM >= 0x070a08
880 { "PROXYAUTH_AVAIL" ,CURLINFO_PROXYAUTH_AVAIL ,RXCURLINFO_BITMAP, NULL },
881 #endif
882 #if LIBCURL_VERSION_NUM >= 0x070907
883 { "REDIRECT_COUNT" ,CURLINFO_REDIRECT_COUNT ,RXCURLINFO_LONG , NULL },
884 { "REDIRECT_TIME" ,CURLINFO_REDIRECT_TIME ,RXCURLINFO_DOUBLE, NULL },
885 #endif
886 #if LIBCURL_VERSION_NUM >= 0x071202
887 { "REDIRECT_URL" ,CURLINFO_REDIRECT_URL ,RXCURLINFO_STRING, NULL },
888 #endif
889 { "REQUEST_SIZE" ,CURLINFO_REQUEST_SIZE ,RXCURLINFO_LONG , NULL },
890 #if LIBCURL_VERSION_NUM >= 0x070a08
891 { "RESPONSE_CODE" ,CURLINFO_RESPONSE_CODE ,RXCURLINFO_LONG , NULL },
892 #endif
893 #if LIBCURL_VERSION_NUM >= 0x071400
894 { "RTSP_CLIENT_CSEQ" ,CURLINFO_RTSP_CLIENT_CSEQ ,RXCURLINFO_LONG , NULL },
895 { "RTSP_CSEQ_RECV" ,CURLINFO_RTSP_CSEQ_RECV ,RXCURLINFO_LONG , NULL },
896 { "RTSP_SERVER_CSEQ" ,CURLINFO_RTSP_SERVER_CSEQ ,RXCURLINFO_LONG , NULL },
897 { "RTSP_SESSION_ID" ,CURLINFO_RTSP_SESSION_ID ,RXCURLINFO_STRING, NULL },
898 #endif
899 { "SIZE_DOWNLOAD" ,CURLINFO_SIZE_DOWNLOAD ,RXCURLINFO_DOUBLE, NULL },
900 { "SIZE_UPLOAD" ,CURLINFO_SIZE_UPLOAD ,RXCURLINFO_DOUBLE, NULL },
901 { "SPEED_DOWNLOAD" ,CURLINFO_SPEED_DOWNLOAD ,RXCURLINFO_DOUBLE, NULL },
902 { "SPEED_UPLOAD" ,CURLINFO_SPEED_UPLOAD ,RXCURLINFO_DOUBLE, NULL },
903 #if LIBCURL_VERSION_NUM >= 0x070c03
904 { "SSL_ENGINES" ,CURLINFO_SSL_ENGINES ,RXCURLINFO_LIST , NULL },
905 #endif
906 { "SSL_VERIFYRESULT" ,CURLINFO_SSL_VERIFYRESULT ,RXCURLINFO_LONG , NULL },
907 #if LIBCURL_VERSION_NUM >= 0x070a02
908 { "STARTTRANSFER_TIME" ,CURLINFO_STARTTRANSFER_TIME ,RXCURLINFO_DOUBLE, NULL },
909 #endif
910 { "TOTAL_TIME" ,CURLINFO_TOTAL_TIME ,RXCURLINFO_DOUBLE, NULL },
911 { NULL ,0 ,0 , NULL }
912 };
913
914 static curl_options RexxCurlSubOptions[] =
915 {
916 { "OLDEST" ,CURLCLOSEPOLICY_OLDEST ,RXCURLOPT_POLICY , NULL },
917 { "LEAST_RECENTLY_USED" ,CURLCLOSEPOLICY_LEAST_RECENTLY_USED,RXCURLOPT_POLICY , NULL },
918 { "LEAST_TRAFFIC" ,CURLCLOSEPOLICY_LEAST_TRAFFIC ,RXCURLOPT_POLICY , NULL },
919 { "SLOWEST" ,CURLCLOSEPOLICY_SLOWEST ,RXCURLOPT_POLICY , NULL },
920 { "CALLBACK" ,CURLCLOSEPOLICY_CALLBACK ,RXCURLOPT_POLICY , NULL },
921 { "NONE" ,CURL_HTTP_VERSION_NONE ,RXCURLOPT_HTTP_VERSION , NULL },
922 { "VERSION_1_0" ,CURL_HTTP_VERSION_1_0 ,RXCURLOPT_HTTP_VERSION , NULL },
923 { "VERSION_1_1" ,CURL_HTTP_VERSION_1_1 ,RXCURLOPT_HTTP_VERSION , NULL },
924 #if LIBCURL_VERSION_NUM >= 0x070a08
925 { "OPTIONAL" ,CURL_NETRC_OPTIONAL ,RXCURLOPT_NETRC , NULL },
926 { "IGNORED" ,CURL_NETRC_IGNORED ,RXCURLOPT_NETRC , NULL },
927 { "REQUIRED" ,CURL_NETRC_REQUIRED ,RXCURLOPT_NETRC , NULL },
928 #endif
929 { "IFMODSINCE" ,CURL_TIMECOND_IFMODSINCE ,RXCURLOPT_TIMECOND , NULL },
930 { "IFUNMODSINCE" ,CURL_TIMECOND_IFUNMODSINCE ,RXCURLOPT_TIMECOND , NULL },
931 { "LASTMOD" ,CURL_TIMECOND_LASTMOD ,RXCURLOPT_TIMECOND , NULL },
932 #if LIBCURL_VERSION_NUM >= 0x070a02
933 { "HTTP" ,CURLPROXY_HTTP ,RXCURLOPT_PROXYTYPE , NULL },
934 { "SOCKS4" ,CURLPROXY_SOCKS4 ,RXCURLOPT_PROXYTYPE , NULL },
935 { "SOCKS5" ,CURLPROXY_SOCKS5 ,RXCURLOPT_PROXYTYPE , NULL },
936 #endif
937 #if LIBCURL_VERSION_NUM >= 0x071304
938 { "HTTP_1_0" ,CURLPROXY_HTTP_1_0 ,RXCURLOPT_PROXYTYPE , NULL },
939 #endif
940 #if LIBCURL_VERSION_NUM >= 0x071200
941 { "SOCKS4A" ,CURLPROXY_SOCKS4A ,RXCURLOPT_PROXYTYPE , NULL },
942 { "SOCKS5_HOSTNAME" ,CURLPROXY_SOCKS5_HOSTNAME ,RXCURLOPT_PROXYTYPE , NULL },
943 #endif
944 #if LIBCURL_VERSION_NUM >= 0x070a08
945 { "WHATEVER" ,CURL_IPRESOLVE_WHATEVER ,RXCURLOPT_IPRESOLVE , NULL },
946 { "V4" ,CURL_IPRESOLVE_V4 ,RXCURLOPT_IPRESOLVE , NULL },
947 { "V6" ,CURL_IPRESOLVE_V6 ,RXCURLOPT_IPRESOLVE , NULL },
948 { "IPRESOLVE_WHATEVER" ,CURL_IPRESOLVE_WHATEVER ,RXCURLOPT_IPRESOLVE , "WHATEVER" },
949 { "IPRESOLVE_V4" ,CURL_IPRESOLVE_V4 ,RXCURLOPT_IPRESOLVE , "V4" },
950 { "IPRESOLVE_V6" ,CURL_IPRESOLVE_V6 ,RXCURLOPT_IPRESOLVE , "V6" },
951 #endif
952 #if LIBCURL_VERSION_NUM >= 0x070a06
953 { "BASIC" ,CURLAUTH_BASIC ,RXCURLOPT_BITMAP_AUTH , NULL },
954 { "DIGEST" ,CURLAUTH_DIGEST ,RXCURLOPT_BITMAP_AUTH , NULL },
955 { "AUTH_BASIC" ,CURLAUTH_BASIC ,RXCURLOPT_BITMAP_AUTH , "BASIC" },
956 { "AUTH_DIGEST" ,CURLAUTH_DIGEST ,RXCURLOPT_BITMAP_AUTH , "DIGEST" },
957 # if LIBCURL_VERSION_NUM >= 0x071303
958 { "DIGEST_IE" ,CURLAUTH_DIGEST_IE ,RXCURLOPT_BITMAP_AUTH , NULL },
959 # endif
960 { "GSSNEGOTIATE" ,CURLAUTH_GSSNEGOTIATE ,RXCURLOPT_BITMAP_AUTH , NULL },
961 { "NTLM" ,CURLAUTH_NTLM ,RXCURLOPT_BITMAP_AUTH , NULL },
962 { "AUTH_GSSNEGOTIATE" ,CURLAUTH_GSSNEGOTIATE ,RXCURLOPT_BITMAP_AUTH , "GSSNEGOTIATE" },
963 { "AUTH_NTLM" ,CURLAUTH_NTLM ,RXCURLOPT_BITMAP_AUTH , "NTLM" },
964 # if LIBCURL_VERSION_NUM >= 0x071600
965 { "NTLM_WB" ,CURLAUTH_NTLM_WB ,RXCURLOPT_BITMAP_AUTH , NULL },
966 # endif
967 { "ANY" ,CURLAUTH_ANY ,RXCURLOPT_BITMAP_AUTH , NULL },
968 { "ANYSAFE" ,CURLAUTH_ANYSAFE ,RXCURLOPT_BITMAP_AUTH , NULL },
969 { "AUTH_ANY" ,CURLAUTH_ANY ,RXCURLOPT_BITMAP_AUTH , "ANY" },
970 { "AUTH_ANYSAFE" ,CURLAUTH_ANYSAFE ,RXCURLOPT_BITMAP_AUTH , "ANYSAFE" },
971 #endif
972 # if LIBCURL_VERSION_NUM >= 0x071503
973 { "ONLY" ,CURLAUTH_ONLY ,RXCURLOPT_BITMAP_AUTH , NULL },
974 { "AUTH_ONLY" ,CURLAUTH_ONLY ,RXCURLOPT_BITMAP_AUTH , "ONLY" },
975 #endif
976 #if LIBCURL_VERSION_NUM >= 0x071001
977 { "PUBLICKEY" ,CURLSSH_AUTH_PUBLICKEY ,RXCURLOPT_BITMAP_SSHAUTH , NULL },
978 { "PASSWORD" ,CURLSSH_AUTH_PASSWORD ,RXCURLOPT_BITMAP_SSHAUTH , NULL },
979 { "HOST" ,CURLSSH_AUTH_HOST ,RXCURLOPT_BITMAP_SSHAUTH , NULL },
980 { "KEYBOARD" ,CURLSSH_AUTH_KEYBOARD ,RXCURLOPT_BITMAP_SSHAUTH , NULL },
981 { "ANY" ,CURLSSH_AUTH_ANY ,RXCURLOPT_BITMAP_SSHAUTH , NULL },
982 { "AUTH_PUBLICKEY" ,CURLSSH_AUTH_PUBLICKEY ,RXCURLOPT_BITMAP_SSHAUTH , "PUBLICKEY" },
983 { "AUTH_PASSWORD" ,CURLSSH_AUTH_PASSWORD ,RXCURLOPT_BITMAP_SSHAUTH , "PASSWORD" },
984 { "AUTH_HOST" ,CURLSSH_AUTH_HOST ,RXCURLOPT_BITMAP_SSHAUTH , "HOST" },
985 { "AUTH_KEYBOARD" ,CURLSSH_AUTH_KEYBOARD ,RXCURLOPT_BITMAP_SSHAUTH , "KEYBOARD" },
986 { "AUTH_ANY" ,CURLSSH_AUTH_ANY ,RXCURLOPT_BITMAP_SSHAUTH , "ANY" },
987 #endif
988 #if LIBCURL_VERSION_NUM >= 0x070b00
989 # if LIBCURL_VERSION_NUM >= 0x071100
990 { "NONE" ,CURLUSESSL_NONE ,RXCURLOPT_FTPSSL , NULL },
991 { "TRY" ,CURLUSESSL_TRY ,RXCURLOPT_FTPSSL , NULL },
992 { "CONTROL" ,CURLUSESSL_CONTROL ,RXCURLOPT_FTPSSL , NULL },
993 { "ALL" ,CURLUSESSL_ALL ,RXCURLOPT_FTPSSL , NULL },
994 # else
995 { "NONE" ,CURLFTPSSL_NONE ,RXCURLOPT_FTPSSL , NULL },
996 { "TRY" ,CURLFTPSSL_TRY ,RXCURLOPT_FTPSSL , NULL },
997 { "CONTROL" ,CURLFTPSSL_CONTROL ,RXCURLOPT_FTPSSL , NULL },
998 { "ALL" ,CURLFTPSSL_ALL ,RXCURLOPT_FTPSSL , NULL },
999 # endif
1000 #endif
1001 #if LIBCURL_VERSION_NUM >= 0x070c02
1002 { "DEFAULT" ,CURLFTPAUTH_DEFAULT ,RXCURLOPT_FTPSSLAUTH , NULL },
1003 { "SSL" ,CURLFTPAUTH_SSL ,RXCURLOPT_FTPSSLAUTH , NULL },
1004 { "TLS" ,CURLFTPAUTH_TLS ,RXCURLOPT_FTPSSLAUTH , NULL },
1005 #endif
1006 #if LIBCURL_VERSION_NUM >= 0x071001
1007 { "NONE" ,CURLFTPSSL_CCC_NONE ,RXCURLOPT_FTPSSLCCC , NULL },
1008 { "PASSIVE" ,CURLFTPSSL_CCC_PASSIVE ,RXCURLOPT_FTPSSLCCC , NULL },
1009 { "ACTIVE" ,CURLFTPSSL_CCC_ACTIVE ,RXCURLOPT_FTPSSLCCC , NULL },
1010 #endif
1011 #if LIBCURL_VERSION_NUM >= 0x071304
1012 { "CREATE_DIR_NONE" ,CURLFTP_CREATE_DIR_NONE ,RXCURLOPT_FTP_CREATE_MISSING_DIRS , NULL },
1013 { "CREATE_DIR" ,CURLFTP_CREATE_DIR ,RXCURLOPT_FTP_CREATE_MISSING_DIRS , NULL },
1014 { "CREATE_DIR_RETRY" ,CURLFTP_CREATE_DIR_RETRY ,RXCURLOPT_FTP_CREATE_MISSING_DIRS , NULL },
1015 #endif
1016 #if LIBCURL_VERSION_NUM >= 0x071400
1017 { "OPTIONS " ,CURL_RTSPREQ_ANNOUNCE ,RXCURLOPT_RTSP_REQUEST , NULL },
1018 { "DESCRIBE" ,CURL_RTSPREQ_SETUP ,RXCURLOPT_RTSP_REQUEST , NULL },
1019 { "ANNOUNCE" ,CURL_RTSPREQ_PLAY ,RXCURLOPT_RTSP_REQUEST , NULL },
1020 { "SETUP" ,CURL_RTSPREQ_PAUSE ,RXCURLOPT_RTSP_REQUEST , NULL },
1021 { "PLAY" ,CURL_RTSPREQ_TEARDOWN ,RXCURLOPT_RTSP_REQUEST , NULL },
1022 { "PAUSE" ,CURL_RTSPREQ_GET_PARAMETER ,RXCURLOPT_RTSP_REQUEST , NULL },
1023 { "TEARDOWN" ,CURL_RTSPREQ_SET_PARAMETER ,RXCURLOPT_RTSP_REQUEST , NULL },
1024 { "GET_PARAMETER" ,CURL_RTSPREQ_RECORD ,RXCURLOPT_RTSP_REQUEST , NULL },
1025 { "SET_PARAMETER" ,CURL_RTSPREQ_RECEIVE ,RXCURLOPT_RTSP_REQUEST , NULL },
1026 #endif
1027 #if LIBCURL_VERSION_NUM >= 0x071304
1028 { "ALL" ,CURLPROTO_ALL ,RXCURLOPT_PROTOCOLS , NULL },
1029 { "HTTP" ,CURLPROTO_HTTP ,RXCURLOPT_PROTOCOLS , NULL },
1030 { "HTTPS" ,CURLPROTO_HTTPS ,RXCURLOPT_PROTOCOLS , NULL },
1031 { "FTP" ,CURLPROTO_FTP ,RXCURLOPT_PROTOCOLS , NULL },
1032 { "FTPS" ,CURLPROTO_FTPS ,RXCURLOPT_PROTOCOLS , NULL },
1033 { "SCP" ,CURLPROTO_SCP ,RXCURLOPT_PROTOCOLS , NULL },
1034 { "SFTP" ,CURLPROTO_SFTP ,RXCURLOPT_PROTOCOLS , NULL },
1035 { "TELNET" ,CURLPROTO_TELNET ,RXCURLOPT_PROTOCOLS , NULL },
1036 { "LDAP" ,CURLPROTO_LDAP ,RXCURLOPT_PROTOCOLS , NULL },
1037 { "LDAPS" ,CURLPROTO_LDAPS ,RXCURLOPT_PROTOCOLS , NULL },
1038 { "DICT" ,CURLPROTO_DICT ,RXCURLOPT_PROTOCOLS , NULL },
1039 { "FILE" ,CURLPROTO_FILE ,RXCURLOPT_PROTOCOLS , NULL },
1040 { "TFTP" ,CURLPROTO_TFTP ,RXCURLOPT_PROTOCOLS , NULL },
1041 #endif
1042 # if LIBCURL_VERSION_NUM >= 0x071400
1043 { "IMAP" ,CURLPROTO_IMAP ,RXCURLOPT_PROTOCOLS , NULL },
1044 { "IMAPS" ,CURLPROTO_IMAPS ,RXCURLOPT_PROTOCOLS , NULL },
1045 { "POP3" ,CURLPROTO_POP3 ,RXCURLOPT_PROTOCOLS , NULL },
1046 { "POP3S" ,CURLPROTO_POP3S ,RXCURLOPT_PROTOCOLS , NULL },
1047 { "SMTP" ,CURLPROTO_SMTP ,RXCURLOPT_PROTOCOLS , NULL },
1048 { "SMTPS" ,CURLPROTO_SMTPS ,RXCURLOPT_PROTOCOLS , NULL },
1049 { "RTSP" ,CURLPROTO_RTSP ,RXCURLOPT_PROTOCOLS , NULL },
1050 #endif
1051 #if LIBCURL_VERSION_NUM >= 0x071600
1052 { "FLAG" ,CURLGSSAPI_DELEGATION_FLAG ,RXCURLOPT_GSSAPI_DELEGATION , NULL },
1053 { "NONE" ,CURLGSSAPI_DELEGATION_NONE ,RXCURLOPT_GSSAPI_DELEGATION , NULL },
1054 { "POLICY_FLAG" ,CURLGSSAPI_DELEGATION_POLICY_FLAG ,RXCURLOPT_GSSAPI_DELEGATION , NULL },
1055 #endif
1056 #if LIBCURL_VERSION_NUM >= 0x071900
1057 { "ALLOW_BEAST" ,CURLSSLOPT_ALLOW_BEAST ,RXCURLOPT_SSL_OPTIONS , NULL },
1058 #endif
1059 #if LIBCURL_VERSION_NUM >= 0x072C00
1060 { "NO_REVOKE" ,CURLSSLOPT_NO_REVOKE ,RXCURLOPT_SSL_OPTIONS , NULL },
1061 #endif
1062 #if LIBCURL_VERSION_NUM >= 0x071301
1063 { "GET_ALL" ,CURL_REDIR_GET_ALL ,RXCURLOPT_BITMAP_REDIR , NULL },
1064 { "POST_301" ,CURL_REDIR_POST_301 ,RXCURLOPT_BITMAP_REDIR , NULL },
1065 { "POST_302" ,CURL_REDIR_POST_302 ,RXCURLOPT_BITMAP_REDIR , NULL },
1066 # if LIBCURL_VERSION_NUM >= 0x071a00
1067 { "POST_303" ,CURL_REDIR_POST_303 ,RXCURLOPT_BITMAP_REDIR , NULL },
1068 # endif
1069 { "POST_ALL" ,CURL_REDIR_POST_ALL ,RXCURLOPT_BITMAP_REDIR , NULL },
1070 #endif
1071 #if LIBCURL_VERSION_NUM >= 0x071504
1072 { "NONE" ,CURL_TLSAUTH_NONE ,RXCURLOPT_BITMAP_TLSAUTH,NULL },
1073 { "SRP" ,CURL_TLSAUTH_SRP ,RXCURLOPT_BITMAP_TLSAUTH,NULL },
1074 #endif
1075 { NULL ,0 ,0 , NULL }
1076 };
1077
1078 #define NUMBER_REXXCURL_OPTIONS (sizeof(RexxCurlOptions)/sizeof(curl_options))
1079 static curl_version_info_data *version_info = NULL;
1080
1081 RxPackageConstantDef RexxCURLConstants[] =
1082 {
1083 { "DIRSEP" , 1, 0 , FILE_SEPARATOR_STR ,0.0, 0 },
1084 { "KHMATCH_MISMATCH", 0, CURLKHMATCH_MISMATCH, NULL, 0.0, 0 },
1085 { "KHMATCH_MISSING", 0, CURLKHMATCH_MISSING, NULL, 0.0, 0 },
1086 { "KHMATCH_OK", 0, CURLKHMATCH_OK, NULL, 0.0, 0 },
1087 { "KHSTAT_DEFER", 0, CURLKHSTAT_DEFER, NULL, 0.0, 0 },
1088 { "KHSTAT_FINE", 0, CURLKHSTAT_FINE, NULL, 0.0, 0 },
1089 { "KHSTAT_FINE_ADD_TO_FILE", 0, CURLKHSTAT_FINE_ADD_TO_FILE, NULL, 0.0, 0 },
1090 { "KHSTAT_REJECT", 0, CURLKHSTAT_REJECT, NULL, 0.0, 0 },
1091 { "KHTYPE_DSS", 0, CURLKHTYPE_DSS, NULL, 0.0, 0 },
1092 { "KHTYPE_RSA", 0, CURLKHTYPE_RSA, NULL, 0.0, 0 },
1093 { "KHTYPE_RSA1", 0, CURLKHTYPE_RSA1, NULL, 0.0, 0 },
1094 { "KHTYPE_UNKNOWN", 0, CURLKHTYPE_UNKNOWN, NULL, 0.0, 0 },
1095 { "PATHSEP" , 1, 0 , PATH_SEPARATOR_STR ,0.0, 0 },
1096 { NULL , 0, 0 , NULL ,0.0, 0 },
1097 };
1098
1099 rxfunc( CurlLoadFuncs );
1100 rxfunc( CurlDropFuncs );
1101 rxfunc( CurlInit );
1102 rxfunc( CurlSetopt );
1103 rxfunc( CurlPerform );
1104 rxfunc( CurlGetinfo );
1105 rxfunc( CurlCleanup );
1106 rxfunc( CurlReset );
1107 rxfunc( CurlVariable );
1108 rxfunc( CurlQueryFunction );
1109 rxfunc( CurlFormAdd );
1110 rxfunc( CurlFormFree );
1111 rxfunc( CurlEscape );
1112 rxfunc( CurlUnescape );
1113
1114 /*-----------------------------------------------------------------------------
1115 * Table of CURL Functions. Used to install/de-install functions.
1116 * If you change this table, don't forget to change the table at the end
1117 * of this file.
1118 *----------------------------------------------------------------------------*/
1119 RexxFunction RexxCURLFunctions[] = {
1120 { "CURLINIT" ,CurlInit ,"CurlInit" , 1 },
1121 { "CURLCLEANUP" ,CurlCleanup ,"CurlCleanup" , 1 },
1122 { "CURLSETOPT" ,CurlSetopt ,"CurlSetopt" , 1 },
1123 { "CURLRESET" ,CurlReset ,"CurlReset" , 1 },
1124 { "CURLPERFORM" ,CurlPerform ,"CurlPerform" , 1 },
1125 { "CURLGETINFO" ,CurlGetinfo ,"CurlGetinfo" , 1 },
1126 { "CURLVARIABLE" ,CurlVariable ,"CurlVariable" , 1 },
1127 { "CURLQUERYFUNCTION",CurlQueryFunction,"CurlQueryFunction", 1 },
1128 { "CURLFORMADD" ,CurlFormAdd ,"CurlFormAdd" , 1 },
1129 { "CURLFORMFREE" ,CurlFormFree ,"CurlFormFree" , 1 },
1130 { "CURLESCAPE" ,CurlEscape ,"CurlEscape" , 1 },
1131 { "CURLUNESCAPE" ,CurlUnescape ,"CurlUnescape" , 1 },
1132 { "CURLDROPFUNCS" ,CurlDropFuncs ,"CurlDropFuncs" , 1 },
1133 { "CURLLOADFUNCS" ,CurlLoadFuncs ,"CurlLoadFuncs" , 0 }, /* Don't load for DLL */
1134 { NULL, NULL, NULL,0 }
1135 };
1136
1137
1138 #define DEFAULT_REXXCURL_ERROR "CURLERROR."
1139 #define INTERRM_PREFIX "INTERRM"
1140 #define INTCODE_PREFIX "INTCODE"
1141 #define CURLERRM_PREFIX "CURLERRM"
1142 #define CURLCODE_PREFIX "CURLCODE"
1143
1144 typedef struct
1145 {
1146 RxPackageGlobalDataDef *RxPackageGlobalData;
1147 RXSTRING str; /* str.strlength identifies how many bytes remaining */
1148 unsigned long index; /* where to start copying data from */
1149 } instem_option;
1150
1151 typedef struct
1152 {
1153 int g_rexxcurl_error;
1154 CURLcode g_curl_error;
1155 char curl_error[CURL_ERROR_SIZE+1];
1156 char rexxcurl_error_prefix[350];
1157 int outstem_index;
1158 int outstem_tail;
1159 char *outstem_strptr;
1160 char *outstem_line_terminator;
1161 int outstem_strlength;
1162 int headerstem_index;
1163 int headerstem_tail;
1164 int progress_index;
1165 rx_long_long max_long;
1166 char UsedOptions[NUMBER_REXXCURL_OPTIONS];
1167 FILE *FilePtrs[NUMBER_REXXCURL_OPTIONS];
1168 char *StringPtrs[NUMBER_REXXCURL_OPTIONS];
1169 instem_option *instem_options[NUMBER_REXXCURL_OPTIONS];
1170 struct curl_slist *SListPtrs[NUMBER_REXXCURL_OPTIONS];
1171 struct curl_httppost *HttpPostFirstPtrs[NUMBER_REXXCURL_OPTIONS];
1172 struct curl_httppost *HttpPostLastPtrs[NUMBER_REXXCURL_OPTIONS];
1173 RxPackageGlobalDataDef *RxPackageGlobalData;
1174 } REXXCURLDATA;
1175
1176 static int have_rexxcallback = API_REXXCALLBACK_MISSING;
1177 static int g_global_init_called = 0;
1178
1179 /*
1180 * If we don't have the RexxFreeMemory() API, then emulate it
1181 */
1182 #ifndef REXXFREEMEMORY
RexxFreeMemory(PVOID ptr)1183 static APIRET APIENTRY RexxFreeMemory( PVOID ptr )
1184 {
1185 #if defined( WIN32 )
1186 GlobalFree( ptr );
1187 #elif defined( __OS2__ )
1188 DosFreeMem( ptr );
1189 #else
1190 free( ptr );
1191 #endif
1192 return 0;
1193 }
1194 # define REXXFREEMEMORY
1195 #endif
1196
1197 /*
1198 * If we don't have the RexxAllocateMemory() API, then emulate it
1199 */
1200 #ifndef REXXALLOCATEMEMORY
RexxAllocateMemory(ULONG size)1201 static PVOID APIENTRY RexxAllocateMemory( ULONG size )
1202 {
1203 PVOID ret;
1204 # if defined( WIN32 )
1205 ret = (PVOID)( GlobalLock( GlobalAlloc ( GMEM_FIXED, size ) ) );
1206 return ret;
1207 # elif defined( __OS2__ )
1208 if ( ( BOOL )DosAllocMem( &ret, size, fPERM|PAG_COMMIT ) )
1209 return NULL;
1210 else
1211 return ret;
1212 # else
1213 ret = (PVOID)malloc( size );
1214 return ret;
1215 # endif
1216 }
1217 # define REXXALLOCATEMEMORY
1218 #endif
1219
1220 #if defined(WIN32)
1221 static CURLcode win32_init(void);
1222 static void win32_cleanup(void);
1223
RexxCURLLoadCURL()1224 void RexxCURLLoadCURL()
1225 {
1226 char LoadError[256];
1227 if ( handle == NULL )
1228 {
1229 handle = LoadLibrary( REXXCURL_LIBCURL_DLL_NAME ) ;
1230 if ( handle == NULL )
1231 {
1232 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1233 fprintf( stderr, "Failed to load cURL dll \"%s\": LoadLibrary() failed: ", REXXCURL_LIBCURL_DLL_NAME );
1234 exit(1);
1235 }
1236
1237 p_curl_easy_init = (T_CURL_EASY_INIT *)GetProcAddress( (HMODULE)handle, "curl_easy_init" );
1238 if ( p_curl_easy_init == NULL )
1239 {
1240 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1241 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: %s", "curl_easy_init", LoadError );
1242 exit(1);
1243 }
1244 p_curl_easy_setopt = (T_CURL_EASY_SETOPT *)GetProcAddress( (HMODULE)handle, "curl_easy_setopt" );
1245 if ( p_curl_easy_setopt == NULL )
1246 {
1247 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1248 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_easy_setopt" );
1249 exit(1);
1250 }
1251 p_curl_easy_reset = (T_CURL_EASY_SETOPT *)GetProcAddress( (HMODULE)handle, "curl_easy_reset" );
1252 if ( p_curl_easy_reset == NULL )
1253 {
1254 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1255 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_easy_reset" );
1256 exit(1);
1257 }
1258 p_curl_easy_getinfo = (T_CURL_EASY_GETINFO *)GetProcAddress( (HMODULE)handle, "curl_easy_getinfo" );
1259 if ( p_curl_easy_getinfo == NULL )
1260 {
1261 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1262 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_easy_getinfo" );
1263 exit(1);
1264 }
1265 p_curl_easy_perform = (T_CURL_EASY_PERFORM *)GetProcAddress( (HMODULE)handle, "curl_easy_perform" );
1266 if ( p_curl_easy_perform == NULL )
1267 {
1268 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1269 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_easy_perform" );
1270 exit(1);
1271 }
1272 p_curl_easy_cleanup = (T_CURL_EASY_CLEANUP *)GetProcAddress( (HMODULE)handle, "curl_easy_cleanup" );
1273 if ( p_curl_easy_cleanup == NULL )
1274 {
1275 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1276 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_easy_cleanup" );
1277 exit(1);
1278 }
1279 p_curl_formadd = (T_CURL_FORMADD *)GetProcAddress( (HMODULE)handle, "curl_formadd" );
1280 if ( p_curl_formadd == NULL )
1281 {
1282 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1283 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_formadd" );
1284 exit(1);
1285 }
1286 p_curl_formfree = (T_CURL_FORMFREE *)GetProcAddress( (HMODULE)handle, "curl_formfree" );
1287 if ( p_curl_formfree == NULL )
1288 {
1289 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1290 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_formfree" );
1291 exit(1);
1292 }
1293 p_curl_global_init = (T_CURL_GLOBAL_INIT *)GetProcAddress( (HMODULE)handle, "curl_global_init" );
1294 if ( p_curl_global_init == NULL )
1295 {
1296 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1297 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_global_init" );
1298 exit(1);
1299 }
1300 p_curl_global_cleanup = (T_CURL_GLOBAL_CLEANUP *)GetProcAddress( (HMODULE)handle, "curl_global_cleanup" );
1301 if ( p_curl_global_cleanup == NULL )
1302 {
1303 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1304 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_global_cleanup" );
1305 exit(1);
1306 }
1307 p_curl_slist_append = (T_CURL_SLIST_APPEND *)GetProcAddress( (HMODULE)handle, "curl_slist_append" );
1308 if ( p_curl_slist_append == NULL )
1309 {
1310 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1311 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_slist_append" );
1312 exit(1);
1313 }
1314 p_curl_slist_free_all = (T_CURL_SLIST_FREE_ALL *)GetProcAddress( (HMODULE)handle, "curl_slist_free_all" );
1315 if ( p_curl_slist_free_all == NULL )
1316 {
1317 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1318 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_slist_free_all" );
1319 exit(1);
1320 }
1321 p_curl_version = (T_CURL_VERSION *)GetProcAddress( (HMODULE)handle, "curl_version" );
1322 if ( p_curl_version == NULL )
1323 {
1324 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1325 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_version" );
1326 exit(1);
1327 }
1328 p_curl_version_info = (T_CURL_VERSION_INFO *)GetProcAddress( (HMODULE)handle, "curl_version_info" );
1329 if ( p_curl_version_info == NULL )
1330 {
1331 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1332 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_version_info" );
1333 exit(1);
1334 }
1335 p_curl_easy_escape = (T_CURL_EASY_ESCAPE *)GetProcAddress( (HMODULE)handle, "curl_easy_escape" );
1336 if ( p_curl_easy_escape == NULL )
1337 {
1338 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1339 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_easy_escape" );
1340 exit(1);
1341 }
1342 p_curl_easy_unescape = (T_CURL_EASY_UNESCAPE *)GetProcAddress( (HMODULE)handle, "curl_easy_unescape" );
1343 if ( p_curl_easy_unescape == NULL )
1344 {
1345 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1346 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_easy_unescape" );
1347 exit(1);
1348 }
1349 p_curl_free = (T_CURL_FREE *)GetProcAddress( (HMODULE)handle, "curl_free" );
1350 if ( p_curl_free == NULL )
1351 {
1352 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT), LoadError, 256, NULL );
1353 fprintf( stderr, "Failed to find \"%s\" in external library: GetProcAddress() failed: ", "curl_free" );
1354 exit(1);
1355 }
1356 }
1357 }
1358
RexxCURLUnloadCURL(void)1359 void RexxCURLUnloadCURL(void)
1360 {
1361 if ( handle )
1362 {
1363 FreeLibrary( handle );
1364 handle = NULL;
1365 }
1366 }
1367 #endif
1368
RexxCURLSetVersionInfoConstants(RxPackageGlobalDataDef * RxPackageGlobalData)1369 void RexxCURLSetVersionInfoConstants( RxPackageGlobalDataDef *RxPackageGlobalData )
1370 {
1371 const char * const*prot;
1372 char name[350];
1373 char value[100];
1374 char *support;
1375 int namelen;
1376 int valuelen;
1377 int count;
1378
1379 InternalTrace( RxPackageGlobalData, "RexxCURLSetVersionInfoConstants", NULL );
1380
1381 namelen = sprintf( name, "%sVERSION", RxGetConstantPrefix( RxPackageGlobalData ) );
1382 SetRexxVariable( RxPackageGlobalData, name, namelen, (char *)version_info->version, (version_info->version) ? strlen( version_info->version ) : 0 );
1383 namelen = sprintf( name, "%sVERSION_NUM", RxGetConstantPrefix( RxPackageGlobalData ) );
1384 valuelen = sprintf( value, "%d", version_info->version_num );
1385 SetRexxVariable( RxPackageGlobalData, name, namelen, value, valuelen );
1386
1387 namelen = sprintf( name, "%sHOST", RxGetConstantPrefix( RxPackageGlobalData ) );
1388 SetRexxVariable( RxPackageGlobalData, name, namelen, (char *)version_info->host, (version_info->host) ? strlen( version_info->host ) : 0 );
1389
1390 namelen = sprintf( name, "%sSSL_VERSION", RxGetConstantPrefix( RxPackageGlobalData ) );
1391 SetRexxVariable( RxPackageGlobalData, name, namelen, (char *)version_info->ssl_version, (version_info->ssl_version) ? strlen( version_info->ssl_version ) : 0 );
1392
1393 namelen = sprintf( name, "%sLIBZ_VERSION", RxGetConstantPrefix( RxPackageGlobalData ) );
1394 SetRexxVariable( RxPackageGlobalData, name, namelen, (char *)version_info->libz_version, (version_info->libz_version) ? strlen( version_info->libz_version ) : 0 );
1395
1396 namelen = sprintf( name, "%sARES", RxGetConstantPrefix( RxPackageGlobalData ) );
1397 SetRexxVariable( RxPackageGlobalData, name, namelen, (char *)version_info->ares, (version_info->ares) ? strlen( version_info->ares ) : 0 );
1398 namelen = sprintf( name, "%sARES_NUM", RxGetConstantPrefix( RxPackageGlobalData ) );
1399 valuelen = sprintf( value, "%d", version_info->ares_num );
1400 SetRexxVariable( RxPackageGlobalData, name, namelen, value, valuelen );
1401
1402 namelen = sprintf( name, "%sLIBIDN", RxGetConstantPrefix( RxPackageGlobalData ) );
1403 SetRexxVariable( RxPackageGlobalData, name, namelen, (char *)version_info->libidn, (version_info->libidn) ? strlen( version_info->libidn ) : 0 );
1404
1405 support = "";
1406 valuelen = 0;
1407 namelen = sprintf( name, "%sLIBSSH_VERSION", RxGetConstantPrefix( RxPackageGlobalData ) );
1408 #if LIBCURL_VERSION_NUM >= 0x071001
1409 support = (char *)version_info->libssh_version;
1410 valuelen = (version_info->libssh_version) ? strlen( version_info->libssh_version ) : 0;
1411 #endif
1412 SetRexxVariable( RxPackageGlobalData, name, namelen, support, valuelen );
1413
1414 namelen = sprintf( name, "%sICONV_VER_NUM", RxGetConstantPrefix( RxPackageGlobalData ) );
1415 support = "0";
1416 valuelen = 1;
1417 #if LIBCURL_VERSION_NUM >= 0x070e05
1418 valuelen = sprintf( value, "%d", version_info->iconv_ver_num );
1419 support = value;
1420 #endif
1421 SetRexxVariable( RxPackageGlobalData, name, namelen, support, valuelen );
1422 /*
1423 * Determine supported features
1424 */
1425 namelen = sprintf( name, "%sSUPPORTS_IPV6", RxGetConstantPrefix( RxPackageGlobalData ) );
1426 SetRexxVariable( RxPackageGlobalData, name, namelen, ( version_info->features & CURL_VERSION_IPV6 ) ? "1" : "0", 1 );
1427 namelen = sprintf( name, "%sSUPPORTS_KERBEROS4", RxGetConstantPrefix( RxPackageGlobalData ) );
1428 SetRexxVariable( RxPackageGlobalData, name, namelen, ( version_info->features & CURL_VERSION_KERBEROS4 ) ? "1" : "0", 1 );
1429
1430 namelen = sprintf( name, "%sSUPPORTS_SSL", RxGetConstantPrefix( RxPackageGlobalData ) );
1431 support = "0";
1432 #if LIBCURL_VERSION_NUM >= 0x070a00
1433 support = ( version_info->features & CURL_VERSION_SSL ) ? "1" : "0";
1434 #endif
1435 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1436
1437 namelen = sprintf( name, "%sSUPPORTS_LIBZ", RxGetConstantPrefix( RxPackageGlobalData ) );
1438 support = "0";
1439 #if LIBCURL_VERSION_NUM >= 0x070a00
1440 support = ( version_info->features & CURL_VERSION_LIBZ ) ? "1" : "0";
1441 #endif
1442 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1443
1444 namelen = sprintf( name, "%sSUPPORTS_NTLM", RxGetConstantPrefix( RxPackageGlobalData ) );
1445 support = "0";
1446 #if LIBCURL_VERSION_NUM >= 0x070a06
1447 support = ( version_info->features & CURL_VERSION_NTLM ) ? "1" : "0";
1448 #endif
1449 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1450
1451 namelen = sprintf( name, "%sSUPPORTS_GSSNEGOTIATE", RxGetConstantPrefix( RxPackageGlobalData ) );
1452 support = "0";
1453 #if LIBCURL_VERSION_NUM >= 0x070a06
1454 support = ( version_info->features & CURL_VERSION_GSSNEGOTIATE ) ? "1" : "0";
1455 #endif
1456 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1457
1458 namelen = sprintf( name, "%sSUPPORTS_DEBUG", RxGetConstantPrefix( RxPackageGlobalData ) );
1459 support = "0";
1460 #if LIBCURL_VERSION_NUM >= 0x070a06
1461 support = ( version_info->features & CURL_VERSION_DEBUG ) ? "1" : "0";
1462 #endif
1463 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1464
1465 namelen = sprintf( name, "%sSUPPORTS_CURLDEBUG", RxGetConstantPrefix( RxPackageGlobalData ) );
1466 support = "0";
1467 #if LIBCURL_VERSION_NUM >= 0x071306
1468 support = ( version_info->features & CURL_VERSION_CURLDEBUG ) ? "1" : "0";
1469 #endif
1470 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1471
1472 namelen = sprintf( name, "%sSUPPORTS_ASYNCHDNS", RxGetConstantPrefix( RxPackageGlobalData ) );
1473 support = "0";
1474 #if LIBCURL_VERSION_NUM >= 0x070a07
1475 support = ( version_info->features & CURL_VERSION_ASYNCHDNS ) ? "1" : "0";
1476 #endif
1477 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1478
1479 namelen = sprintf( name, "%sSUPPORTS_SPNEGO", RxGetConstantPrefix( RxPackageGlobalData ) );
1480 support = "0";
1481 #if LIBCURL_VERSION_NUM >= 0x070a08
1482 support = ( version_info->features & CURL_VERSION_SPNEGO ) ? "1" : "0";
1483 #endif
1484 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1485
1486 namelen = sprintf( name, "%sSUPPORTS_LARGEFILE", RxGetConstantPrefix( RxPackageGlobalData ) );
1487 support = "0";
1488 #if LIBCURL_VERSION_NUM >= 0x070b01
1489 support = ( version_info->features & CURL_VERSION_LARGEFILE ) ? "1" : "0";
1490 #endif
1491 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1492
1493 namelen = sprintf( name, "%sSUPPORTS_IDN", RxGetConstantPrefix( RxPackageGlobalData ) );
1494 support = "0";
1495 #if LIBCURL_VERSION_NUM >= 0x070c00
1496 support = ( version_info->features & CURL_VERSION_IDN ) ? "1" : "0";
1497 #endif
1498 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1499
1500 namelen = sprintf( name, "%sSUPPORTS_SSPI", RxGetConstantPrefix( RxPackageGlobalData ) );
1501 support = "0";
1502 #if LIBCURL_VERSION_NUM >= 0x070d02
1503 support = ( version_info->features & CURL_VERSION_SSPI ) ? "1" : "0";
1504 #endif
1505 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1506
1507 namelen = sprintf( name, "%sSUPPORTS_CONV", RxGetConstantPrefix( RxPackageGlobalData ) );
1508 support = "0";
1509 #if LIBCURL_VERSION_NUM >= 0x070e04
1510 support = ( version_info->features & CURL_VERSION_CONV ) ? "1" : "0";
1511 #endif
1512 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1513
1514 namelen = sprintf( name, "%sSUPPORTS_TLSAUTH_SRP", RxGetConstantPrefix( RxPackageGlobalData ) );
1515 support = "0";
1516 #if LIBCURL_VERSION_NUM >= 0x071504
1517 support = ( version_info->features & CURL_VERSION_TLSAUTH_SRP ) ? "1" : "0";
1518 #endif
1519 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1520
1521 namelen = sprintf( name, "%sSUPPORTS_NTLM_WB", RxGetConstantPrefix( RxPackageGlobalData ) );
1522 support = "0";
1523 #if LIBCURL_VERSION_NUM >= 0x071600
1524 support = ( version_info->features & CURL_VERSION_NTLM_WB ) ? "1" : "0";
1525 #endif
1526 SetRexxVariable( RxPackageGlobalData, name, namelen, support, 1 );
1527 /*
1528 * Set supported protocols
1529 */
1530 prot = version_info->protocols;
1531 count = 1;
1532 while ( *prot )
1533 {
1534 namelen = sprintf( name, "%sPROTOCOLS.%d", RxGetConstantPrefix( RxPackageGlobalData ), count );
1535 SetRexxVariable( RxPackageGlobalData, name, namelen, (char *)*prot, strlen( *prot ) );
1536 prot++;
1537 count++;
1538 }
1539 namelen = sprintf( name, "%sPROTOCOLS.0", RxGetConstantPrefix( RxPackageGlobalData ) );
1540 valuelen = sprintf( value, "%d", count-1 );
1541 SetRexxVariable( RxPackageGlobalData, name, namelen, value, valuelen );
1542 }
1543
1544 /*
1545 * These functions used by loader.c to obtain package-specific info
1546 * There probably is no need for this function at all as the INI EXIT should
1547 * do all the work! FIX ME
1548 */
RexxCURLInitialiser(RxPackageGlobalDataDef * RxPackageGlobalData)1549 int RexxCURLInitialiser( RxPackageGlobalDataDef *RxPackageGlobalData )
1550 {
1551 InternalTrace( RxPackageGlobalData, "RexxCURLInitialiser", NULL );
1552 #if 0
1553
1554 #if defined(WIN32)
1555 RexxCURLLoadCURL();
1556 #endif
1557 /*
1558 * Check the version of the library we have loaded at runtime against the version we support;
1559 * not necessarily the version we built with.
1560 * We crash and burn if the version at runtime is < the supported version
1561 */
1562 version_info = CURL_VERSION_INFO(CURLVERSION_NOW);
1563 if ( version_info )
1564 {
1565 if ( version_info->version_num < LIBCURL_SUPPORTED_VERSION )
1566 {
1567 fprintf(stderr,"WARNING! Incompatible version of cURL found. The version of cURL found: %s is less than the supported version: %s.\n", version_info->version, LIBCURL_VERSION );
1568 }
1569 /*
1570 * Set our version info variables
1571 */
1572 RexxCURLSetVersionInfoConstants( RxPackageGlobalData );
1573 }
1574 #endif
1575 return 0;
1576 }
1577
RexxCURLTerminator(RxPackageGlobalDataDef * RxPackageGlobalData)1578 int RexxCURLTerminator( RxPackageGlobalDataDef *RxPackageGlobalData )
1579 {
1580 InternalTrace( RxPackageGlobalData , "RexxCURLTerminator", NULL );
1581 CURL_GLOBAL_CLEANUP();
1582 #if defined(WIN32)
1583 RexxCURLUnloadCURL();
1584 // win32_cleanup();
1585 #endif
1586 return 0;
1587 }
1588
1589 /*
1590 * Every package MUST have one of these, otherwise ooRexx will crash
1591 */
RexxCURLInitHandler(REH_ARG0_TYPE ExitNum,REH_ARG1_TYPE Subfun,REH_ARG2_TYPE PBlock)1592 REH_RETURN RexxCURLInitHandler( REH_ARG0_TYPE ExitNum, REH_ARG1_TYPE Subfun, REH_ARG2_TYPE PBlock )
1593 {
1594 unsigned long tmp_long;
1595 REXXCURLDATA *RexxCURLData;
1596 /*
1597 * Get thread-safe-data
1598 */
1599 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
1600 InternalTrace(RxPackageGlobalData ,"RexxCURLInitHandler", "ExitNum %ld Subfun %ld",ExitNum, Subfun);
1601 #if defined(WIN32)
1602 /*
1603 * Load the entry points for the libcurl DLL
1604 */
1605 RexxCURLLoadCURL();
1606 #endif
1607 /*
1608 * Determine if the Rexx interpreter has RexxCallBack()
1609 * If USE_REGINA then we have it.
1610 * If USE_REXXTRANS then we MIGHT have it; we need to call RxTransHaveRexxCallBack()
1611 * to check.
1612 * If REXXCALLBACK defined, then we also have it.
1613 * All other situations, we DON'T have it.
1614 * We need to determine this BEFORE calling SetPackageConstants()
1615 */
1616 #if defined( USE_REGINA )
1617 have_rexxcallback = API_REXXCALLBACK_PRESENT;
1618 #elif defined ( USE_REXXTRANS )
1619 if ( RexxTransHaveRexxCallBack() )
1620 have_rexxcallback = API_REXXCALLBACK_PRESENT;
1621 #elif defined( REXXCALLBACK )
1622 have_rexxcallback = API_REXXCALLBACK_PRESENT;
1623 #else
1624 /*
1625 * The default value for HAVE_REXXCALLBACK variable is not set, so we don't have to change anything
1626 */
1627 #endif
1628 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
1629 #if defined(WIN32_NOT_REQUIRED)
1630 if ( win32_init() )
1631 return 1;
1632 #endif
1633 if ( !g_global_init_called )
1634 {
1635 g_global_init_called = 1;
1636 CURL_GLOBAL_INIT(CURL_GLOBAL_ALL);
1637 }
1638 strcpy( RexxCURLData->rexxcurl_error_prefix, DEFAULT_REXXCURL_ERROR );
1639 /*
1640 * Get ourselves the maximum value of an unsigned long into max_long
1641 * to use when determining if we need to use long longs later
1642 */
1643 memset( &tmp_long, 0xFF, sizeof(tmp_long) );
1644 RexxCURLData->max_long = (rx_long_long)(tmp_long/2);
1645 SetPackageConstants( RxPackageGlobalData, RexxCURLConstants, 0 );
1646 /*
1647 * Check the version of the library we have loaded at runtime against the version we support;
1648 * not necessarily the version we built with.
1649 * We crash and burn if the version at runtime is < the supported version
1650 */
1651 version_info = CURL_VERSION_INFO(CURLVERSION_NOW);
1652 if ( version_info )
1653 {
1654 if ( version_info->version_num < LIBCURL_SUPPORTED_VERSION )
1655 {
1656 fprintf(stderr,"WARNING! Incompatible version of cURL found. The version of cURL found: %s is less than the supported version: %s.\n", version_info->version, LIBCURL_VERSION );
1657 }
1658 /*
1659 * Set our version info variables
1660 */
1661 RexxCURLSetVersionInfoConstants( RxPackageGlobalData );
1662 }
1663 return 0L;
1664 }
1665
RexxCURLTermHandler(LONG ExitNum,LONG Subfun,PEXIT PBlock)1666 LONG APIENTRY RexxCURLTermHandler( LONG ExitNum, LONG Subfun, PEXIT PBlock )
1667 {
1668 DEBUGDUMP(fprintf(stderr,"%s-%d: In rexxcurlTermHandler() ExitNum %ld Subfun %ld\n",__FILE__,__LINE__,ExitNum, Subfun);)
1669 return 0L;
1670 }
1671
getRexxCURLSubcomHandler(void)1672 RexxSubcomHandler *getRexxCURLSubcomHandler( void )
1673 {
1674 return NULL;
1675 }
1676
getRexxCURLInitHandler(void)1677 RexxExitHandler *getRexxCURLInitHandler( void )
1678 {
1679 return RexxCURLInitHandler;
1680 }
1681
getRexxCURLTermHandler(void)1682 RexxExitHandler *getRexxCURLTermHandler( void )
1683 {
1684 return RexxCURLTermHandler;
1685 }
1686
getRexxCURLFunctions(void)1687 RexxFunction *getRexxCURLFunctions( void )
1688 {
1689 return RexxCURLFunctions;
1690 }
1691
getRexxCURLConstants(void)1692 RxPackageConstantDef *getRexxCURLConstants( void )
1693 {
1694 return RexxCURLConstants;
1695 }
1696
getRexxCURLInitialiser(void)1697 PackageInitialiser *getRexxCURLInitialiser( void )
1698 {
1699 return RexxCURLInitialiser;
1700 }
1701
getRexxCURLTerminator(void)1702 PackageTerminator *getRexxCURLTerminator( void )
1703 {
1704 return RexxCURLTerminator;
1705 }
1706
getRexxCURLFunctionAddress(char * name)1707 void *getRexxCURLFunctionAddress( char *name )
1708 {
1709 int i, size = sizeof( RexxCURLFunctions ) / sizeof( RexxFunction ) ;
1710
1711 for (i = 0; i < size && RexxCURLFunctions[i].InternalName; i++)
1712 {
1713 if ( strcmp( RexxCURLFunctions[i].InternalName, name) == 0 )
1714 return RexxCURLFunctions[i].EntryPoint;
1715 }
1716 return NULL;
1717 }
1718
INIT_RXPACKAGE(RxPackageGlobalDataDef * RxPackageGlobalData)1719 void *INIT_RXPACKAGE ( RxPackageGlobalDataDef *RxPackageGlobalData )
1720 {
1721 /*
1722 * This needs to allocate memory for RexxCURLData structure,
1723 */
1724 RxPackageGlobalData->RXPACKAGE_tsd = (REXXCURLDATA *)MALLOC_TSD( RxPackageGlobalData, sizeof(REXXCURLDATA) );
1725 if ( RxPackageGlobalData->RXPACKAGE_tsd )
1726 memset( RxPackageGlobalData->RXPACKAGE_tsd , 0, sizeof(REXXCURLDATA) );
1727 /*
1728 * TODO
1729 * If any global variable that require initialisation or allocation of memory, add them here
1730 */
1731 return (void *)RxPackageGlobalData->RXPACKAGE_tsd;
1732 }
1733
TERM_RXPACKAGE(RxPackageGlobalDataDef * RxPackageGlobalData)1734 void TERM_RXPACKAGE ( RxPackageGlobalDataDef *RxPackageGlobalData )
1735 {
1736 /*
1737 * This needs to free memory allocated in INIT_RXPACKAGE()
1738 * and call any database-specific termination code
1739 */
1740 /*
1741 * Get the TSD if required
1742 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
1743 */
1744 /*
1745 * Free any items in the RexxCURLData struct that were allocated in INIT_RXPACKAGE
1746 */
1747 /*
1748 * Free the RexxCURLData struct
1749 */
1750 FREE_TSD( RxPackageGlobalData, RxPackageGlobalData->RXPACKAGE_tsd );
1751 RxPackageGlobalData = NULL;
1752 }
1753
1754 #if defined(WIN32)
win32_cleanup(void)1755 static void win32_cleanup(void)
1756 {
1757 WSACleanup();
1758 }
1759
win32_init(void)1760 static CURLcode win32_init(void)
1761 {
1762 WORD wVersionRequested;
1763 WSADATA wsaData;
1764 int err;
1765 wVersionRequested = MAKEWORD(1, 1);
1766
1767 err = WSAStartup(wVersionRequested, &wsaData);
1768
1769 if (err != 0)
1770 /* Tell the user that we couldn't find a useable */
1771 /* winsock.dll. */
1772 return 1;
1773
1774 /* Confirm that the Windows Sockets DLL supports 1.1.*/
1775 /* Note that if the DLL supports versions greater */
1776 /* than 1.1 in addition to 1.1, it will still return */
1777 /* 1.1 in wVersion since that is the version we */
1778 /* requested. */
1779
1780 if ( LOBYTE( wsaData.wVersion ) != 1 ||
1781 HIBYTE( wsaData.wVersion ) != 1 ) {
1782 /* Tell the user that we couldn't find a useable */
1783
1784 /* winsock.dll. */
1785 WSACleanup();
1786 return 1;
1787 }
1788 return 0; /* 0 is ok */
1789 }
1790 #endif
1791
1792 /*-----------------------------------------------------------------------------
1793 * This function is the callback for PROGRESSFUNCTION option.
1794 * We need the client data pointer to get the TSD.
1795 *----------------------------------------------------------------------------*/
rexxcurl_progress_callback(void * clientp,double dltotal,double dlnow,double ultotal,double ulnow)1796 int rexxcurl_progress_callback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
1797 {
1798 int num_args = 4;
1799 char rx_dltotal[20];
1800 char rx_dlnow[20];
1801 char rx_ultotal[20];
1802 char rx_ulnow[20];
1803 PRXSTRING argv;
1804 RXSTRING RetStr;
1805 int rc;
1806 SHORT rcode=0;
1807 REXXCURLDATA *RexxCURLData;
1808 RxPackageGlobalDataDef *RxPackageGlobalData = (RxPackageGlobalDataDef *)clientp;
1809
1810 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
1811
1812 if ( have_rexxcallback )
1813 {
1814 argv = (PRXSTRING)malloc( num_args*sizeof(RXSTRING) );
1815 if ( argv == NULL )
1816 return -1;
1817 sprintf( rx_dltotal, "%0.f", dltotal );
1818 sprintf( rx_dlnow, "%0.f", dlnow );
1819 sprintf( rx_ultotal, "%0.f", ultotal );
1820 sprintf( rx_ulnow, "%0.f", ulnow );
1821 MAKERXSTRING( argv[0], rx_dltotal, strlen( rx_dltotal ) );
1822 MAKERXSTRING( argv[1], rx_dlnow, strlen( rx_dlnow ) );
1823 MAKERXSTRING( argv[2], rx_ultotal, strlen( rx_ultotal ) );
1824 MAKERXSTRING( argv[3], rx_ulnow, strlen( rx_ulnow ) );
1825
1826 MAKERXSTRING( RetStr, NULL, 0 );
1827 #if defined( REXXCALLBACK )
1828 rc = RexxCallBack( RexxCURLData->StringPtrs[RexxCURLData->progress_index], num_args, argv, &rcode, &RetStr );
1829 #else
1830 rc = 0;
1831 #endif
1832 if ( RetStr.strptr )
1833 RexxFreeMemory( RetStr.strptr );
1834 free( argv );
1835 /* free_cb_argv( curr );*/
1836 }
1837 return rcode;
1838 }
1839
1840 /*-----------------------------------------------------------------------------
1841 * This function is the callback for SSHKEYFUNCTION option.
1842 * We need the client data pointer to get the TSD.
1843 * Args to Rexx procedure:
1844 * knownkeystring - value of key
1845 * knownkeylength - length of known key; 0 indicates base64 encoding, otherwise raw
1846 * knownkeytype - KHTYPE_UNKNOWN, KHTYPE_RSA, KHTYPE_RSA1, KHTYPE_DSS
1847 * foundkeystring - value of key
1848 * foundkeylength - length of found key; 0 indicates base64 encoding, otherwise raw
1849 * foundkeytype - KHTYPE_UNKNOWN, KHTYPE_RSA, KHTYPE_RSA1, KHTYPE_DSS
1850 * libcurlviewofkey - KHMATCH_OK (match), KHMATCH_MISMATCH (host found, key mismatch!), KHMATCH_MISSING (no matching host/key found)
1851 *----------------------------------------------------------------------------*/
rexxcurl_sshkey_callback(CURL * easy,const struct curl_khkey * knownkey,const struct curl_khkey * foundkey,enum curl_khmatch match,void * clientp)1852 int rexxcurl_sshkey_callback( CURL *easy, /* easy handle; ignored */
1853 const struct curl_khkey *knownkey, /* known */
1854 const struct curl_khkey *foundkey, /* found */
1855 enum curl_khmatch match, /* libcurl's view on the keys */
1856 void *clientp) /* custom pointer passed from app */
1857 {
1858 int num_args = 7;
1859 char rx_knownkeylength[20];
1860 char rx_knownkeytype[20];
1861 char rx_foundkeylength[20];
1862 char rx_foundkeytype[20];
1863 char rx_libcurlviewofkey[20];
1864 int rx_knownkeylength_len;
1865 int rx_knownkeytype_len;
1866 int rx_foundkeylength_len;
1867 int rx_foundkeytype_len;
1868 int rx_libcurlviewofkey_len;
1869 PRXSTRING argv;
1870 RXSTRING RetStr;
1871 int rc;
1872 SHORT rcode=0;
1873 REXXCURLDATA *RexxCURLData;
1874 RxPackageGlobalDataDef *RxPackageGlobalData = (RxPackageGlobalDataDef *)clientp;
1875
1876 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
1877
1878 if ( have_rexxcallback )
1879 {
1880 argv = (PRXSTRING)malloc( num_args*sizeof(RXSTRING) );
1881 if ( argv == NULL )
1882 return -1;
1883
1884 rx_knownkeylength_len = sprintf( rx_knownkeylength, "%lu", (unsigned long) knownkey->len );
1885 rx_knownkeytype_len = sprintf( rx_knownkeytype, "%u", knownkey->keytype );
1886 rx_foundkeylength_len = sprintf( rx_foundkeylength, "%lu", (unsigned long) foundkey->len );
1887 rx_foundkeytype_len = sprintf( rx_foundkeytype, "%u", foundkey->keytype );
1888 rx_libcurlviewofkey_len = sprintf( rx_libcurlviewofkey, "%u", match );
1889
1890 if ( knownkey->len )
1891 {
1892 MAKERXSTRING( argv[0], knownkey->key, knownkey->len );
1893 }
1894 else
1895 {
1896 MAKERXSTRING( argv[0], knownkey->key, strlen( knownkey->key ) );
1897 }
1898 MAKERXSTRING( argv[1], rx_knownkeylength, rx_knownkeylength_len );
1899 MAKERXSTRING( argv[2], rx_knownkeytype, rx_knownkeytype_len );
1900 if ( foundkey->len )
1901 {
1902 MAKERXSTRING( argv[3], foundkey->key, foundkey->len );
1903 }
1904 else
1905 {
1906 MAKERXSTRING( argv[3], foundkey->key, strlen( foundkey->key ) );
1907 }
1908 MAKERXSTRING( argv[4], rx_foundkeylength, rx_foundkeylength_len );
1909 MAKERXSTRING( argv[5], rx_foundkeytype, rx_foundkeytype_len );
1910 MAKERXSTRING( argv[6], rx_libcurlviewofkey, rx_libcurlviewofkey_len );
1911
1912 MAKERXSTRING( RetStr, NULL, 0 );
1913 #if defined( REXXCALLBACK )
1914 rc = RexxCallBack( RexxCURLData->StringPtrs[RexxCURLData->progress_index], num_args, argv, &rcode, &RetStr );
1915 #else
1916 rc = 0;
1917 #endif
1918 if ( RetStr.strptr )
1919 RexxFreeMemory( RetStr.strptr );
1920 free( argv );
1921 /* free_cb_argv( curr );*/
1922 }
1923 return rcode;
1924 }
1925
1926 /*-----------------------------------------------------------------------------
1927 * This function returns the size of the specified file. Returns -1 if the
1928 * file does not exist or is not a "normal" file eg a directory
1929 *----------------------------------------------------------------------------*/
get_file_size(RxPackageGlobalDataDef * RxPackageGlobalData,char * fn)1930 rx_long_long get_file_size( RxPackageGlobalDataDef *RxPackageGlobalData, char *fn )
1931 {
1932 struct stat stat_buf;
1933 size_t rc;
1934 rx_long_long fs;
1935
1936 rc = stat( fn, &stat_buf ) ;
1937 if (rc == 0)
1938 {
1939 if ( (stat_buf.st_mode & S_IFMT) == S_IFDIR)
1940 fs = -1;
1941 else
1942 fs = (rx_long_long)stat_buf.st_size;
1943 }
1944 else
1945 fs = (rx_long_long)rc;
1946 InternalTrace( RxPackageGlobalData, "get_file_size", "Size of file: %s is: %ld", fn, fs );
1947 return fs;
1948 }
1949
1950 /*-----------------------------------------------------------------------------
1951 * This function is necessary for Win32/64 platform
1952 * To use InternalTrace we would need to get TSD each time; very inefficient
1953 *----------------------------------------------------------------------------*/
file_write_function(void * ptr,size_t size,size_t nmemb,void * stream)1954 size_t file_write_function( void *ptr, size_t size, size_t nmemb, void *stream )
1955 {
1956 return fwrite( ptr, size, nmemb, stream );
1957 }
1958
1959 /*-----------------------------------------------------------------------------
1960 * This function is necessary for Win32/64 platform
1961 * To use InternalTrace we would need to get TSD each time; very inefficient
1962 *----------------------------------------------------------------------------*/
debug_function(CURL * handle,curl_infotype type,char * data,size_t size,void * userdata)1963 int debug_function( CURL *handle, curl_infotype type, char *data, size_t size, void *userdata )
1964 {
1965 FILE *fp = (FILE *)userdata;
1966 int c;
1967 char *prefix = "*<><><>";
1968 if ( type == CURLINFO_TEXT )
1969 fprintf( fp, "text: %c %.*s", prefix[type],(int)size, data );
1970 if ( type == CURLINFO_HEADER_IN )
1971 fprintf( fp, "header_in: %c %.*s", prefix[type],(int)size, data );
1972 if ( type == CURLINFO_HEADER_OUT )
1973 fprintf( fp, "header_out:%c %.*s", prefix[type],(int)size, data );
1974 if ( type == CURLINFO_SSL_DATA_IN )
1975 {
1976 fprintf( fp, "ssl_data_in: " );
1977 for ( c = 0; c < size; c++ )
1978 {
1979 char x = (data[c] >= 0x20) ? data[c] : '.';
1980 fputc( x, fp);
1981 }
1982 fputc('\n', fp); /* newline */
1983 }
1984 if ( type == CURLINFO_SSL_DATA_OUT )
1985 {
1986 fprintf( fp, "ssl_data_out: " );
1987 for ( c = 0; c < size; c++ )
1988 {
1989 char x = (data[c] >= 0x20) ? data[c] : '.';
1990 fputc( x, fp);
1991 }
1992 fputc('\n', fp); /* newline */
1993 }
1994 return 0;
1995 }
1996
1997
1998 /*-----------------------------------------------------------------------------
1999 * This function is necessary for Win32/64 platform
2000 * To use InternalTrace we would need to get TSD each time; very inefficient
2001 *----------------------------------------------------------------------------*/
file_read_function(void * ptr,size_t size,size_t nmemb,void * stream)2002 size_t file_read_function( void *ptr, size_t size, size_t nmemb, void *stream )
2003 {
2004 return fread( ptr, size, nmemb, stream );
2005 }
2006
stem_read_function(void * ptr,size_t size,size_t nmemb,void * data)2007 size_t stem_read_function( void *ptr, size_t size, size_t nmemb, void *data )
2008 {
2009 instem_option *opt = (instem_option *)data;
2010 int count = size*nmemb; /* requested size to return */
2011 char *str;
2012 if ( opt->str.strlength )
2013 {
2014 int copy_this_much = opt->str.strlength;
2015 if ( copy_this_much > count)
2016 {
2017 copy_this_much = count;
2018 }
2019 InternalTrace( opt->RxPackageGlobalData, "stem_read_function", "Requested size: %ld Remaining: %ld Returning count: %ld", count, opt->str.strlength, copy_this_much );
2020 str = opt->str.strptr + opt->index;
2021
2022 memcpy(ptr, str, copy_this_much);
2023 opt->str.strlength -= copy_this_much;
2024 opt->index += copy_this_much;
2025 return copy_this_much;
2026 }
2027 InternalTrace( opt->RxPackageGlobalData, "stem_read_function", "Complete!" );
2028 return 0;
2029 }
2030
2031 /*-----------------------------------------------------------------------------
2032 * This function creates a compound Rexx variable with the supplied name
2033 * and vale.
2034 *----------------------------------------------------------------------------*/
create_rexx_compound(RxPackageGlobalDataDef * RxPackageGlobalData,char * stem,int tail,char * value,int valuelen)2035 int create_rexx_compound( RxPackageGlobalDataDef *RxPackageGlobalData, char *stem, int tail, char *value, int valuelen )
2036 {
2037 char name[350];
2038 int namelen;
2039
2040 namelen = sprintf( name, "%s%d", stem, tail );
2041 SetRexxVariable( RxPackageGlobalData, name, namelen, value, valuelen );
2042 return 0;
2043 }
2044 /*-----------------------------------------------------------------------------
2045 * This function writes the output from the site to a stem. Called from
2046 * OUTSTEM option
2047 *----------------------------------------------------------------------------*/
outstem_write_function(void * ptr,size_t size,size_t nmemb,void * stream)2048 size_t outstem_write_function( void *ptr, size_t size, size_t nmemb, void *stream )
2049 {
2050 size_t num_bytes=size*nmemb;
2051 size_t rc;
2052 REXXCURLDATA *RexxCURLData;
2053 /*
2054 * Get thread-safe-data
2055 */
2056 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
2057
2058 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2059
2060 InternalTrace( RxPackageGlobalData, "outstem_write_function", "Size of chunk to write: %ld", num_bytes );
2061 if ( RexxCURLData->outstem_strlength)
2062 RexxCURLData->outstem_strptr = (char *)realloc( RexxCURLData->outstem_strptr, RexxCURLData->outstem_strlength + num_bytes + 1);
2063 else
2064 RexxCURLData->outstem_strptr = (char *)malloc( RexxCURLData->outstem_strlength + num_bytes + 1);
2065
2066 if ( RexxCURLData->outstem_strptr == NULL )
2067 {
2068 rc = -1;
2069 }
2070 else
2071 {
2072 memcpy( RexxCURLData->outstem_strptr+RexxCURLData->outstem_strlength, ptr, num_bytes );
2073 RexxCURLData->outstem_strlength += num_bytes;
2074 RexxCURLData->outstem_strptr[RexxCURLData->outstem_strlength] = '\0';
2075 rc = num_bytes;
2076 }
2077 InternalTrace( RxPackageGlobalData, "outstem_write_function", "Returned with: %ld", num_bytes );
2078 return rc;
2079 }
2080 /*-----------------------------------------------------------------------------
2081 * This function creates the compound variables for the stem.
2082 *----------------------------------------------------------------------------*/
outstem_create(RxPackageGlobalDataDef * RxPackageGlobalData)2083 int outstem_create( RxPackageGlobalDataDef *RxPackageGlobalData )
2084 {
2085 char *tmp,*ptr;
2086 char *eol;
2087 int eollen;
2088 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2089
2090 if ( RexxCURLData->outstem_strptr )
2091 {
2092 eol = RexxCURLData->outstem_line_terminator;
2093 eollen = strlen( eol );
2094 ptr = RexxCURLData->outstem_strptr;
2095 tmp = strstr( ptr, eol );
2096
2097 while( tmp != NULL )
2098 {
2099 *tmp = '\0';
2100 create_rexx_compound( RxPackageGlobalData, RexxCURLData->StringPtrs[RexxCURLData->outstem_index], ++(RexxCURLData->outstem_tail), (char *)ptr, strlen( ptr ) );
2101 ptr = tmp+eollen;
2102 tmp = strstr( ptr, eol );
2103 }
2104 if ( *ptr != '\0' )
2105 {
2106 create_rexx_compound( RxPackageGlobalData, RexxCURLData->StringPtrs[RexxCURLData->outstem_index], ++(RexxCURLData->outstem_tail), (char *)ptr, strlen( ptr ) );
2107 }
2108 }
2109
2110 return 0;
2111 }
2112 /*-----------------------------------------------------------------------------
2113 * This function writes the output from the site to a stem. Called from
2114 * HEADERSTEM option
2115 *----------------------------------------------------------------------------*/
headerstem_write_function(void * ptr,size_t size,size_t nmemb,void * stream)2116 size_t headerstem_write_function( void *ptr, size_t size, size_t nmemb, void *stream )
2117 {
2118 size_t num_bytes=size*nmemb;
2119 REXXCURLDATA *RexxCURLData;
2120 /*
2121 * Get thread-safe-data
2122 */
2123 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
2124 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2125 /*
2126 * We are guaranteed that each header is complete and terminated with CRLF, so simply
2127 * set the length of the variable value to 2 less than actual length
2128 */
2129 create_rexx_compound( RxPackageGlobalData , RexxCURLData->StringPtrs[RexxCURLData->headerstem_index], ++(RexxCURLData->headerstem_tail), (char *)ptr, num_bytes - 2 );
2130 /*
2131 * Tell cURL we've read ALL bytes
2132 */
2133 return num_bytes;
2134 }
2135
2136 /*-----------------------------------------------------------------------------
2137 * Clear the cURL error message.
2138 *----------------------------------------------------------------------------*/
ClearCURLError(RxPackageGlobalDataDef * RxPackageGlobalData)2139 void ClearCURLError( RxPackageGlobalDataDef *RxPackageGlobalData )
2140 {
2141 char var[350];
2142 int varlen;
2143 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2144
2145 InternalTrace( RxPackageGlobalData, "ClearCURLError", NULL );
2146 /*
2147 * Set CURLERROR.CURLERRM variable
2148 */
2149 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, CURLERRM_PREFIX );
2150 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, "", 0 );
2151 /*
2152 * Set CURLERROR.CURLCODE variable
2153 */
2154 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, CURLCODE_PREFIX );
2155 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, "0", 1 );
2156 RexxCURLData->g_curl_error = 0;
2157 return;
2158 }
2159
2160 /*-----------------------------------------------------------------------------
2161 * Set the cURL error message.
2162 *----------------------------------------------------------------------------*/
SetCURLError(RxPackageGlobalDataDef * RxPackageGlobalData,CURLcode curlcode,char * curlmsg)2163 void SetCURLError( RxPackageGlobalDataDef *RxPackageGlobalData, CURLcode curlcode, char *curlmsg)
2164 {
2165 char var[350];
2166 char msg[350];
2167 int varlen;
2168 int msglen;
2169 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2170
2171 InternalTrace( RxPackageGlobalData, "SetCURLError", "%d,%s", curlcode, curlmsg );
2172
2173 RexxCURLData->g_curl_error = curlcode;
2174 /*
2175 * Set CURLERROR.CURLERRM variable
2176 */
2177 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, CURLERRM_PREFIX );
2178 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, curlmsg, strlen(curlmsg) );
2179 /*
2180 * Set CURLERROR.CURLCODE variable
2181 */
2182 msglen = sprintf( msg, "%d", RexxCURLData->g_curl_error );
2183 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, CURLCODE_PREFIX );
2184 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, msg, msglen );
2185 return;
2186 }
2187
2188 /*-----------------------------------------------------------------------------
2189 * Clear the internal error message.
2190 *----------------------------------------------------------------------------*/
ClearIntError(RxPackageGlobalDataDef * RxPackageGlobalData)2191 static int ClearIntError( RxPackageGlobalDataDef *RxPackageGlobalData )
2192 {
2193 char var[350];
2194 int varlen;
2195 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2196
2197 InternalTrace( RxPackageGlobalData, "ClearIntError", NULL );
2198
2199 RexxCURLData->g_rexxcurl_error = 0;
2200 /*
2201 * Set CURLERROR.INTERRM variable
2202 */
2203 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, INTERRM_PREFIX );
2204 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, "", 0 );
2205 /*
2206 * Set CURLERROR.INTCODE variable
2207 */
2208 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, INTCODE_PREFIX );
2209 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, "0", 1 );
2210
2211 return( RexxCURLData->g_rexxcurl_error );
2212 }
2213
2214 /*-----------------------------------------------------------------------------
2215 * Set the internal error message.
2216 *----------------------------------------------------------------------------*/
SetIntError(RxPackageGlobalDataDef * RxPackageGlobalData,char * fn,int lineno,int errcode,char * errmsg)2217 static int SetIntError( RxPackageGlobalDataDef *RxPackageGlobalData, char *fn, int lineno, int errcode, char *errmsg )
2218 {
2219 char msg[350];
2220 char var[350];
2221 int msglen;
2222 int varlen;
2223 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2224
2225 InternalTrace( RxPackageGlobalData, "SetIntError", "%s,%d,%d,%s", fn, lineno, errcode, errmsg );
2226
2227 RexxCURLData->g_rexxcurl_error = -errcode;
2228
2229 /*
2230 * Set CURLERROR.INTERRM variable
2231 */
2232 if ( RxGetRunFlags( RxPackageGlobalData ) & MODE_INTERNAL )
2233 msglen = sprintf(msg, "Rexx/CURL-%02d: %s [%s:%d]", errcode, errmsg, fn, lineno);
2234 else
2235 msglen = sprintf(msg, "REXX/CURL-%02d: %s", errcode, errmsg);
2236 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, INTERRM_PREFIX );
2237 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, msg, msglen );
2238
2239 /*
2240 * Set CURLERROR.INTCODE variable
2241 */
2242 msglen = sprintf( msg, "%d", RexxCURLData->g_rexxcurl_error );
2243 varlen = sprintf( var,"%s%s", RexxCURLData->rexxcurl_error_prefix, INTCODE_PREFIX );
2244 (void)SetRexxVariable( RxPackageGlobalData, var, varlen, msg, msglen );
2245
2246 return( RexxCURLData->g_rexxcurl_error );
2247 }
2248
init_options(RxPackageGlobalDataDef * RxPackageGlobalData)2249 static void init_options( RxPackageGlobalDataDef *RxPackageGlobalData )
2250 {
2251 int i;
2252 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2253
2254 InternalTrace( RxPackageGlobalData, "init_options", NULL );
2255
2256 for ( i = 0; i < NUMBER_REXXCURL_OPTIONS; i++ )
2257 {
2258 RexxCURLData->FilePtrs[i] = NULL;
2259 RexxCURLData->StringPtrs[i] = NULL;
2260 RexxCURLData->SListPtrs[i] = NULL;
2261 RexxCURLData->HttpPostFirstPtrs[i] = NULL;
2262 RexxCURLData->HttpPostLastPtrs[i] = NULL;
2263 RexxCURLData->UsedOptions[i] = '\0';
2264 }
2265 }
2266
reset_options(RxPackageGlobalDataDef * RxPackageGlobalData)2267 static void reset_options( RxPackageGlobalDataDef *RxPackageGlobalData )
2268 {
2269 int i;
2270 REXXCURLDATA *RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2271
2272 for ( i = 0; i < NUMBER_REXXCURL_OPTIONS; i++ )
2273 {
2274 if ( RexxCURLData->FilePtrs[i] )
2275 {
2276 fclose( RexxCURLData->FilePtrs[i] );
2277 RexxCURLData->FilePtrs[i] = NULL;
2278 }
2279 if ( RexxCURLData->StringPtrs[i] )
2280 {
2281 free( RexxCURLData->StringPtrs[i] );
2282 RexxCURLData->StringPtrs[i] = NULL;
2283 }
2284 if ( RexxCURLData->SListPtrs[i] )
2285 {
2286 CURL_SLIST_FREE_ALL( RexxCURLData->SListPtrs[i] );
2287 RexxCURLData->SListPtrs[i] = NULL;
2288 }
2289 if ( RexxCURLData->HttpPostFirstPtrs[i] )
2290 {
2291 CURL_FORMFREE( RexxCURLData->HttpPostFirstPtrs[i] );
2292 RexxCURLData->HttpPostFirstPtrs[i] = NULL;
2293 RexxCURLData->HttpPostLastPtrs[i] = NULL;
2294 }
2295 RexxCURLData->UsedOptions[i] = '\0';
2296 }
2297 }
2298
find_option(RxPackageGlobalDataDef * RxPackageGlobalData,char * str,int len)2299 static int find_option( RxPackageGlobalDataDef *RxPackageGlobalData, char *str, int len )
2300 {
2301 register int i = 0;
2302
2303 for ( i = 0; RexxCurlOptions[i].name != NULL; i++ )
2304 {
2305 if ( memcmpi( RxPackageGlobalData, str, RexxCurlOptions[i].name, len ) == 0 )
2306 {
2307 /*
2308 * If this is a deprecated option name, print a warning with the new name
2309 */
2310 if ( RexxCurlOptions[i].newname )
2311 {
2312 fprintf( stderr,"WARNING: The option \"%s\" is deprecated. Use option \"%s\" instead.\n", RexxCurlOptions[i].name, RexxCurlOptions[i].newname );
2313 }
2314 return i;
2315 }
2316 }
2317 return ( -1 );
2318 }
2319
find_getinfo(RxPackageGlobalDataDef * RxPackageGlobalData,char * str,int len)2320 static int find_getinfo( RxPackageGlobalDataDef *RxPackageGlobalData, char *str, int len )
2321 {
2322 register int i = 0;
2323
2324 for ( i = 0; RexxCurlGetinfos[i].name != NULL; i++ )
2325 {
2326 if ( memcmpi( RxPackageGlobalData, str, RexxCurlGetinfos[i].name, len ) == 0 )
2327 {
2328 /*
2329 * If this is a deprecated option name, print a warning with the new name
2330 */
2331 if ( RexxCurlGetinfos[i].newname )
2332 {
2333 fprintf( stderr,"WARNING: The info option \"%s\" is deprecated. Use info option \"%s\" instead.\n", RexxCurlGetinfos[i].name, RexxCurlGetinfos[i].newname );
2334 }
2335 return i;
2336 }
2337 }
2338 return ( -1 );
2339 }
2340
find_suboption(RxPackageGlobalDataDef * RxPackageGlobalData,char * str,int len,int optiontype)2341 static int find_suboption( RxPackageGlobalDataDef *RxPackageGlobalData, char *str, int len, int optiontype )
2342 {
2343 register int i = 0;
2344
2345 for ( i = 0; RexxCurlSubOptions[i].name != NULL; i++ )
2346 {
2347 if ( memcmpi( RxPackageGlobalData, str, RexxCurlSubOptions[i].name, len ) == 0
2348 && RexxCurlSubOptions[i].optiontype == optiontype )
2349 {
2350 /*
2351 * If this is a deprecated option name, print a warning with the new name
2352 */
2353 if ( RexxCurlSubOptions[i].newname )
2354 {
2355 fprintf( stderr,"WARNING: The sub-option \"%s\" is deprecated. Use sub-option \"%s\" instead.\n", RexxCurlSubOptions[i].name, RexxCurlSubOptions[i].newname );
2356 }
2357 return i;
2358 }
2359 }
2360 return ( -1 );
2361 }
2362
2363 /*====== Here come the real interface functions to curl ======*/
2364
rxfunc(CurlInit)2365 rxfunc( CurlInit )
2366 {
2367 CURL *curl;
2368 REXXCURLDATA *RexxCURLData;
2369 /*
2370 * Get thread-safe-data
2371 */
2372 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
2373 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
2374 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2375
2376 ClearCURLError( RxPackageGlobalData );
2377 ClearIntError( RxPackageGlobalData );
2378 if ( my_checkparam( RxPackageGlobalData, name, argc, 0, 0 ) )
2379 return( 1 );
2380 /*
2381 * Do some initialisations
2382 */
2383 init_options( RxPackageGlobalData );
2384 curl = CURL_EASY_INIT();
2385 InternalTrace( RxPackageGlobalData, "CurlInit", "After curl_easy_init" );
2386 /*
2387 * Determine if the Rexx interpreter has RexxCallBack()
2388 * If USE_REGINA then we have it.
2389 * If USE_REXXTRANS then we MIGHT have it; we need to call RxTransHaveRexxCallBack()
2390 * to check.
2391 * If REXXCALLBACK defined, then we also have it.
2392 * All other situations, we DON'T have it.
2393 * We need to determine this BEFORE calling SetPackageConstants()
2394 */
2395 #if defined( USE_REGINA )
2396 have_rexxcallback = 1;
2397 InternalTrace( RxPackageGlobalData, "CurlInit", "RexxCallback available: Regina" );
2398 #elif defined ( USE_REXXTRANS )
2399 if ( RexxTransHaveRexxCallBack() )
2400 have_rexxcallback = 1;
2401 InternalTrace( RxPackageGlobalData, "CurlInit", "RexxCallback %s: RexxTrans", have_rexxcallback ? "available" : "unavailable" );
2402 #elif defined( REXXCALLBACK )
2403 have_rexxcallback = 1;
2404 InternalTrace( RxPackageGlobalData, "CurlInit", "RexxCallback available: Other Interpreter" );
2405 #else
2406 have_rexxcallback = 0;
2407 InternalTrace( RxPackageGlobalData, "CurlInit", "RexxCallback unavailable: Other Interpreter" );
2408 #endif
2409 return RxReturnPointer( RxPackageGlobalData, retstr, (void *)curl ) ;
2410 }
2411
rxfunc(CurlCleanup)2412 rxfunc( CurlCleanup )
2413 {
2414 long curl;
2415 REXXCURLDATA *RexxCURLData;
2416 /*
2417 * Get thread-safe-data
2418 */
2419 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
2420 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
2421 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2422
2423 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
2424 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
2425 if ( my_checkparam( RxPackageGlobalData, name, argc, 1, 1 ) )
2426 return( 1 );
2427 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
2428 {
2429 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
2430 return RxReturnNumber( RxPackageGlobalData, retstr, INTERR_INVALID_HANDLE ) ;
2431 }
2432 CURL_EASY_CLEANUP( (CURL *)curl );
2433 reset_options( RxPackageGlobalData );
2434 memset( RexxCURLData->UsedOptions, 0, sizeof(char)*NUMBER_REXXCURL_OPTIONS );
2435 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
2436 }
2437
rxfunc(CurlSetopt)2438 rxfunc( CurlSetopt )
2439 {
2440 ULONG rc = 0L;
2441 long curl;
2442 int i,j,opt,sub_opt;
2443 long long_opt;
2444 rx_long_long longlong_opt;
2445 rx_long_long file_size;
2446 CURLcode curl_rc;
2447 CURLFORMcode curlformadd_rc;
2448 RXSTRING value;
2449 int ltlen;
2450 int count = 0;
2451 char *ltstr;
2452 char *tmp;
2453 char eol[2]={10,0};
2454 char tmp_format[100];
2455 char *opentype="wb";
2456 REXXCURLDATA *RexxCURLData;
2457 /*
2458 * Get thread-safe-data
2459 */
2460 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
2461 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
2462 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
2463
2464 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
2465 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
2466 if ( my_checkparam( RxPackageGlobalData, name, argc, 2, 0 ) )
2467 return( 1 );
2468 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
2469 {
2470 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
2471 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
2472 }
2473 opt = find_option( RxPackageGlobalData, argv[1].strptr, argv[1].strlength );
2474 if ( opt == (-1) )
2475 {
2476 char buf[1024];
2477 sprintf( buf, "%s: %s", INTERR_INVALID_OPTION_STRING, argv[1].strptr );
2478 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, buf );
2479 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
2480 }
2481 /*
2482 * HTTPPOSTDATA does NOT require any further arguments, so only if it is NOT
2483 * this option, check for the mandatory 3rd argument
2484 */
2485 if ( RexxCurlOptions[opt].optiontype != RXCURLOPT_POST_FORM )
2486 {
2487 if ( my_checkparam( RxPackageGlobalData, name, argc, 3, 0 ) )
2488 return( 1 );
2489 }
2490
2491 switch( RexxCurlOptions[opt].optiontype )
2492 {
2493 case RXCURLOPT_STRING:
2494 if ( RexxCURLData->StringPtrs[opt] )
2495 {
2496 free( RexxCURLData->StringPtrs[opt] );
2497 RexxCURLData->StringPtrs[opt] = NULL;
2498 }
2499 RexxCURLData->StringPtrs[opt] = (char *)malloc( argv[2].strlength + 1 );
2500 if ( RexxCURLData->StringPtrs[opt] == NULL )
2501 {
2502 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
2503 break;
2504 }
2505 memcpy( RexxCURLData->StringPtrs[opt], argv[2].strptr, argv[2].strlength );
2506 RexxCURLData->StringPtrs[opt][argv[2].strlength] = '\0';
2507 /*
2508 * Do any extra processing here for some options
2509 */
2510 switch( RexxCurlOptions[opt].number )
2511 {
2512 default:
2513 break;
2514 }
2515 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->StringPtrs[opt] );
2516 if ( curl_rc != CURLE_OK )
2517 {
2518 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2519 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2520 break;
2521 }
2522 break;
2523 case RXCURLOPT_OUTFILE:
2524 /* check if APPEND passed as optional argument */
2525 if ( argc == 4
2526 && argv[3].strlength )
2527 {
2528 if ( memcmpi( RxPackageGlobalData, argv[3].strptr, "APPEND", 6 ) == 0 )
2529 opentype = "ab";
2530 }
2531 /* parameter must be the name of a file to write to or blank to turn it off */
2532 if ( argv[2].strlength )
2533 {
2534 RexxCURLData->FilePtrs[opt] = fopen( argv[2].strptr, opentype );
2535 if ( RexxCURLData->FilePtrs[opt] == NULL )
2536 {
2537 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_FILE, INTERR_INVALID_FILE_STRING );
2538 break;
2539 }
2540 }
2541 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->FilePtrs[opt] );
2542 if ( curl_rc != CURLE_OK )
2543 {
2544 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2545 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2546 break;
2547 }
2548 switch ( RexxCurlOptions[opt].number )
2549 {
2550 #if LIBCURL_VERSION_NUM >= 0x072600
2551 case CURLOPT_WRITEDATA:
2552 case CURLOPT_HEADERDATA:
2553 #else
2554 case CURLOPT_FILE:
2555 case CURLOPT_WRITEHEADER:
2556 #endif
2557 if ( argv[2].strlength )
2558 {
2559 /*
2560 * Always set the write function if we have an output file
2561 */
2562 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_WRITEFUNCTION, &file_write_function );
2563 if ( curl_rc != CURLE_OK )
2564 {
2565 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2566 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2567 break;
2568 }
2569 }
2570 break;
2571 default:
2572 break;
2573 }
2574 break;
2575 case RXCURLOPT_ERRFILE:
2576 /* check if APPEND passed as optional argument */
2577 if ( argc == 4
2578 && argv[3].strlength )
2579 {
2580 if ( memcmpi( RxPackageGlobalData, argv[3].strptr, "APPEND", 6 ) == 0 )
2581 opentype = "ab";
2582 }
2583 /* parameter must be the name of a file to write to or blank to turn it off */
2584 if ( argv[2].strlength )
2585 {
2586 RexxCURLData->FilePtrs[opt] = fopen( argv[2].strptr, opentype );
2587 if ( RexxCURLData->FilePtrs[opt] == NULL )
2588 {
2589 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_FILE, INTERR_INVALID_FILE_STRING );
2590 break;
2591 }
2592 }
2593 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->FilePtrs[opt] );
2594 if ( curl_rc != CURLE_OK )
2595 {
2596 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2597 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2598 break;
2599 }
2600 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_DEBUGDATA, RexxCURLData->FilePtrs[opt] );
2601 if ( curl_rc != CURLE_OK )
2602 {
2603 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2604 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2605 break;
2606 }
2607 switch ( RexxCurlOptions[opt].number )
2608 {
2609 case CURLOPT_STDERR:
2610 if ( argv[2].strlength )
2611 {
2612 /*
2613 * Always set the write function if we have an output file
2614 */
2615 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_DEBUGFUNCTION, &debug_function );
2616 if ( curl_rc != CURLE_OK )
2617 {
2618 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2619 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2620 break;
2621 }
2622 }
2623 break;
2624 default:
2625 break;
2626 }
2627 break;
2628
2629 case RXCURLOPT_INFILE:
2630 /* parameter must be the name of a file to read from or blank to turn it off */
2631 if ( argv[2].strlength )
2632 {
2633 RexxCURLData->FilePtrs[opt] = fopen( argv[2].strptr, "rb" );
2634 if ( RexxCURLData->FilePtrs[opt] == NULL )
2635 {
2636 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_FILE, INTERR_INVALID_FILE_STRING );
2637 break;
2638 }
2639 }
2640 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->FilePtrs[opt] );
2641 if ( curl_rc != CURLE_OK )
2642 {
2643 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2644 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2645 break;
2646 }
2647 /*
2648 * Now do some extra stuff depending on the option specified...
2649 */
2650 switch ( RexxCurlOptions[opt].number )
2651 {
2652 #if LIBCURL_VERSION_NUM >= 0x072600
2653 case CURLOPT_READDATA:
2654 #else
2655 case CURLOPT_INFILE:
2656 #endif
2657 /*
2658 * Always set the file size for the specified INFILE
2659 */
2660 if ( argv[2].strlength )
2661 {
2662 file_size = get_file_size( RxPackageGlobalData, argv[2].strptr );
2663 }
2664 else
2665 {
2666 file_size = 0;
2667 }
2668 if ( file_size == -1 )
2669 {
2670 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_FILE, INTERR_INVALID_FILE_STRING );
2671 break;
2672 }
2673 /*
2674 * Determine which option to use based on file size
2675 */
2676 #if LIBCURL_VERSION_NUM >= 0x070b00
2677 if ( file_size > RexxCURLData->max_long )
2678 {
2679 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_INFILESIZE_LARGE, file_size );
2680 }
2681 else
2682 #endif
2683 {
2684 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_INFILESIZE, (long)file_size );
2685 }
2686 if ( curl_rc != CURLE_OK )
2687 {
2688 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2689 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2690 break;
2691 }
2692 if ( argv[2].strlength )
2693 {
2694 /*
2695 * Always set the read function if we have an input file. This is because
2696 * Win32/64 port requires it!
2697 */
2698 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_READFUNCTION, &file_read_function );
2699 if ( curl_rc != CURLE_OK )
2700 {
2701 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2702 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2703 break;
2704 }
2705 }
2706 break;
2707 default:
2708 break;
2709 }
2710
2711 break;
2712 case RXCURLOPT_INFILENAME:
2713 if ( argv[2].strlength == 0
2714 && RexxCurlOptions[opt].number == CURLOPT_COOKIEFILE )
2715 {
2716 /* parameter can be blank for COOKIEFILE */
2717 }
2718 else
2719 {
2720 /* parameter must be the name of a file that we can read; so open it */
2721 RexxCURLData->FilePtrs[opt] = fopen( argv[2].strptr, "rb" );
2722 if ( RexxCURLData->FilePtrs[opt] == NULL )
2723 {
2724 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_FILE, INTERR_INVALID_FILE_STRING );
2725 break;
2726 }
2727 /* close the file and set ptr to NULL */
2728 fclose( RexxCURLData->FilePtrs[opt] );
2729 break;
2730 }
2731 RexxCURLData->FilePtrs[opt] = NULL;
2732
2733 /* copy the arg to pass to cURL */
2734 if ( RexxCURLData->StringPtrs[opt] )
2735 free( RexxCURLData->StringPtrs[opt] );
2736 RexxCURLData->StringPtrs[opt] = (char *)malloc( argv[2].strlength + 1 );
2737 if ( RexxCURLData->StringPtrs[opt] == NULL )
2738 {
2739 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
2740 break;
2741 }
2742 memcpy( RexxCURLData->StringPtrs[opt], argv[2].strptr, argv[2].strlength );
2743 RexxCURLData->StringPtrs[opt][argv[2].strlength] = '\0';
2744 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->StringPtrs[opt] );
2745 if ( curl_rc != CURLE_OK )
2746 {
2747 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2748 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2749 break;
2750 }
2751
2752 break;
2753 case RXCURLOPT_INSTEM:
2754 /*
2755 * Check that arg[2] is a stem, then convert the stem into
2756 * a string of values
2757 */
2758 if ( argv[2].strlength
2759 && argv[2].strptr[argv[2].strlength-1] != '.' )
2760 {
2761 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
2762 break;
2763 }
2764 if ( GetRexxVariableInteger( RxPackageGlobalData, argv[2].strptr, &sub_opt, 0 ) == NULL )
2765 {
2766 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
2767 break;
2768 }
2769 /*
2770 * Reset the rxstring ptr if previously set
2771 */
2772 if ( RexxCURLData->instem_options[opt] )
2773 {
2774 if (RexxCURLData->instem_options[opt]->str.strptr)
2775 {
2776 free( RexxCURLData->instem_options[opt]->str.strptr );
2777 }
2778 RexxCURLData->instem_options[opt]->str.strlength = 0;
2779 RexxCURLData->instem_options[opt]->str.strptr = NULL;
2780 RexxCURLData->instem_options[opt]->str.strlength = 0;
2781 RexxCURLData->instem_options[opt]->index = 0;
2782 free( RexxCURLData->instem_options[opt] );
2783 RexxCURLData->instem_options[opt] = NULL;
2784 }
2785 /*
2786 * Allocate new instem_option
2787 */
2788 RexxCURLData->instem_options[opt] = (instem_option *)malloc( sizeof(instem_option) );
2789 if ( RexxCURLData->instem_options[opt] == NULL )
2790 {
2791 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
2792 break;
2793 }
2794
2795 for ( i = 1; i <= sub_opt; i++ )
2796 {
2797 if ( GetRexxVariable( RxPackageGlobalData, argv[2].strptr, &value, i ) == NULL )
2798 {
2799 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
2800 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
2801 }
2802 if ( RexxCURLData->instem_options[opt]->str.strptr == NULL )
2803 {
2804 RexxCURLData->instem_options[opt]->str.strptr = (char *)malloc( value.strlength + 2 );
2805 if ( RexxCURLData->instem_options[opt]->str.strptr == NULL )
2806 {
2807 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
2808 break;
2809 }
2810 strcpy( RexxCURLData->instem_options[opt]->str.strptr, "" );
2811 RexxCURLData->instem_options[opt]->str.strlength = 0;
2812 RexxCURLData->instem_options[opt]->index = 0;
2813 RexxCURLData->instem_options[opt]->RxPackageGlobalData = RxPackageGlobalData;
2814 // tmp = RexxCURLData->RxStrings[opt].strptr;
2815 }
2816 else
2817 {
2818 RexxCURLData->instem_options[opt]->str.strptr = (char *)realloc( RexxCURLData->instem_options[opt]->str.strptr, RexxCURLData->instem_options[opt]->str.strlength + value.strlength + 2);
2819 if ( RexxCURLData->instem_options[opt]->str.strptr == NULL )
2820 {
2821 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
2822 break;
2823 }
2824 }
2825 strcat( RexxCURLData->instem_options[opt]->str.strptr, value.strptr );
2826 RexxCURLData->instem_options[opt]->str.strlength += value.strlength;
2827 /*
2828 * Free the memory allocated in GetRexxVariable()
2829 */
2830 FREE_TSD( RxPackageGlobalData, value.strptr );
2831 }
2832 InternalTrace( RxPackageGlobalData, "CurlSetopt(RXCURLOPT_INSTEM)", "Value: <%s>", (RexxCURLData->instem_options[opt]->str.strptr) ? RexxCURLData->instem_options[opt]->str.strptr : "" );
2833
2834 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_POSTFIELDSIZE, RexxCURLData->instem_options[opt]->str.strlength );
2835 if ( curl_rc != CURLE_OK )
2836 {
2837 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2838 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2839 break;
2840 }
2841 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_READFUNCTION, stem_read_function );
2842 if ( curl_rc != CURLE_OK )
2843 {
2844 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2845 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2846 break;
2847 }
2848 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_READDATA, RexxCURLData->instem_options[opt] );
2849 if ( curl_rc != CURLE_OK )
2850 {
2851 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2852 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2853 break;
2854 }
2855 break;
2856 case RXCURLOPT_LONG:
2857 if ( RxStrToLong( RxPackageGlobalData, &argv[2], &long_opt ) != 0 )
2858 {
2859 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_NUMBER, INTERR_INVALID_NUMBER_STRING );
2860 break;
2861 }
2862 FunctionTrace( RxPackageGlobalData, "CurlSetopt", "Setting LONG value: %ld", long_opt );
2863 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, long_opt );
2864 if ( curl_rc != CURLE_OK )
2865 {
2866 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2867 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2868 break;
2869 }
2870 break;
2871 case RXCURLOPT_LONGLONG:
2872 {
2873 CURLoption opt_num;
2874 int opt_long_long = 0;
2875
2876 /*
2877 * Do we try and compare the passed value against MAX_LONG and call
2878 * the LONG option setting instead of the LARGE option???????
2879 */
2880 opt_num = RexxCurlOptions[opt].number;
2881 switch ( RexxCurlOptions[opt].number )
2882 {
2883 #if LIBCURL_VERSION_NUM >= 0x070b00
2884 case CURLOPT_RESUME_FROM:
2885 opt_num = CURLOPT_RESUME_FROM_LARGE;
2886 opt_long_long = 1;
2887 break;
2888 #endif
2889 #if LIBCURL_VERSION_NUM >= 0x070a09
2890 case CURLOPT_MAXFILESIZE:
2891 opt_num = CURLOPT_MAXFILESIZE_LARGE;
2892 opt_long_long = 1;
2893 break;
2894 #endif
2895 #if LIBCURL_VERSION_NUM >= 0x070e05
2896 case CURLOPT_MAX_SEND_SPEED_LARGE:
2897 opt_long_long = 1;
2898 break;
2899 #endif
2900 #if LIBCURL_VERSION_NUM >= 0x070e05
2901 case CURLOPT_MAX_RECV_SPEED_LARGE:
2902 opt_long_long = 1;
2903 break;
2904 #endif
2905 default:
2906 break;
2907 }
2908 if ( opt_long_long )
2909 {
2910 if ( RxStrToLongLong( RxPackageGlobalData, &argv[2], &longlong_opt ) != 0 )
2911 {
2912 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_NUMBER, INTERR_INVALID_NUMBER_STRING );
2913 break;
2914 }
2915 sprintf( tmp_format, "Setting LONGLONG value: %s", RX_LL_FORMAT );
2916 FunctionTrace( RxPackageGlobalData, "CurlSetopt", tmp_format, longlong_opt );
2917 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, opt_num, longlong_opt );
2918 }
2919 else
2920 {
2921 if ( RxStrToLong( RxPackageGlobalData, &argv[2], &long_opt ) != 0 )
2922 {
2923 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_NUMBER, INTERR_INVALID_NUMBER_STRING );
2924 break;
2925 }
2926 FunctionTrace( RxPackageGlobalData, "CurlSetopt", "Setting LONG(LONG) value: %ld", long_opt );
2927 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, opt_num, long_opt );
2928 }
2929 if ( curl_rc != CURLE_OK )
2930 {
2931 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2932 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2933 break;
2934 }
2935 break;
2936 }
2937 case RXCURLOPT_BOOL:
2938 if ( RxStrToBool( RxPackageGlobalData, &argv[2], (unsigned long *)&long_opt ) != 0 )
2939 {
2940 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_BOOL, INTERR_INVALID_BOOL_STRING );
2941 break;
2942 }
2943 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, long_opt );
2944 if ( curl_rc != CURLE_OK )
2945 {
2946 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2947 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2948 break;
2949 }
2950 break;
2951 case RXCURLOPT_BITMAP_AUTH:
2952 case RXCURLOPT_BITMAP_REDIR:
2953 case RXCURLOPT_BITMAP_SSHAUTH:
2954 case RXCURLOPT_FTPSSL:
2955 case RXCURLOPT_FTPSSLAUTH:
2956 case RXCURLOPT_FTPSSLCCC:
2957 case RXCURLOPT_SSL_OPTIONS:
2958 long_opt = 0L;
2959 for ( i = 2; i < (int)argc; i++ )
2960 {
2961 sub_opt = find_suboption( RxPackageGlobalData, argv[i].strptr, argv[i].strlength, RexxCurlOptions[opt].optiontype );
2962 if ( sub_opt == (-1) )
2963 {
2964 char buf[1024];
2965 sprintf( buf, "%s: %s", INTERR_INVALID_OPTION_STRING, argv[i].strptr );
2966 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, buf );
2967 break;
2968 }
2969 long_opt |= RexxCurlSubOptions[sub_opt].number;
2970 }
2971 if ( sub_opt == (-1) )
2972 break;
2973 FunctionTrace( RxPackageGlobalData, "CurlSetopt", "Setting BITMAP value: %x", long_opt );
2974 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, long_opt );
2975 if ( curl_rc != CURLE_OK )
2976 {
2977 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
2978 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
2979 break;
2980 }
2981 break;
2982 case RXCURLOPT_POLICY:
2983 case RXCURLOPT_PROXYTYPE:
2984 case RXCURLOPT_HTTP_VERSION:
2985 case RXCURLOPT_NETRC:
2986 case RXCURLOPT_TIMECOND:
2987 case RXCURLOPT_IPRESOLVE:
2988 case RXCURLOPT_FTP_CREATE_MISSING_DIRS:
2989 case RXCURLOPT_RTSP_REQUEST:
2990 case RXCURLOPT_PROTOCOLS:
2991 /*
2992 * This handles sub-options that result in a long value passed to CURL_EASY_SETOPT()
2993 */
2994 sub_opt = find_suboption( RxPackageGlobalData, argv[2].strptr, argv[2].strlength, RexxCurlOptions[opt].optiontype );
2995 if ( sub_opt == (-1) )
2996 {
2997 char buf[1024];
2998 sprintf( buf, "%s: %s", INTERR_INVALID_OPTION_STRING, argv[2].strptr );
2999 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, buf );
3000 break;
3001 }
3002 long_opt = RexxCurlSubOptions[sub_opt].number;
3003 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, long_opt );
3004 if ( curl_rc != CURLE_OK )
3005 {
3006 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3007 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3008 break;
3009 }
3010 break;
3011 case RXCURLOPT_LIST:
3012 /*
3013 * Check that arg[2] is a stem, then convert the stem into
3014 * a cURL linked list
3015 */
3016 if ( argv[2].strptr[argv[2].strlength-1] != '.' )
3017 {
3018 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3019 break;
3020 }
3021 /* can't do this on ooRexx 4.x as strptr is const argv[2].strptr[argv[2].strlength] = '\0'; */
3022 if ( GetRexxVariableInteger( RxPackageGlobalData, argv[2].strptr, &sub_opt, 0 ) == NULL )
3023 {
3024 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3025 break;
3026 }
3027 if ( RexxCURLData->SListPtrs[opt] )
3028 {
3029 CURL_SLIST_FREE_ALL( RexxCURLData->SListPtrs[opt] );
3030 RexxCURLData->SListPtrs[opt] = NULL;
3031 }
3032 for ( i = 1; i <= sub_opt; i++ )
3033 {
3034 if ( GetRexxVariable( RxPackageGlobalData, argv[2].strptr, &value, i ) == NULL )
3035 {
3036 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3037 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3038 }
3039 InternalTrace( RxPackageGlobalData, "CurlSetopt(RXCURLOPT_LIST)", "Variable: <%s%d> Value: <%s>", argv[2].strptr, i, value.strptr );
3040 RexxCURLData->SListPtrs[opt] = CURL_SLIST_APPEND( RexxCURLData->SListPtrs[opt], value.strptr );
3041 /*
3042 * Free the memory allocated in GetRexxVariable()
3043 */
3044 FREE_TSD( RxPackageGlobalData, value.strptr );
3045 if ( RexxCURLData->SListPtrs[opt] == NULL )
3046 {
3047 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3048 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3049 }
3050 }
3051 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->SListPtrs[opt] );
3052 if ( curl_rc != CURLE_OK )
3053 {
3054 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3055 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3056 break;
3057 }
3058 break;
3059 case RXCURLOPT_POST_DATA:
3060 /*
3061 * Check that arg[2] is a stem, then convert the stem into a name/value pair for formdata
3062 */
3063 if ( argv[2].strlength
3064 && argv[2].strptr[argv[2].strlength-1] != '.' )
3065 {
3066 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3067 break;
3068 }
3069 /* can't do this on ooRexx 4.x as strptr is const argv[2].strptr[argv[2].strlength] = '\0'; */
3070 if ( GetRexxVariableInteger( RxPackageGlobalData, argv[2].strptr, &sub_opt, 0 ) == NULL )
3071 {
3072 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3073 break;
3074 }
3075 if ( RexxCURLData->HttpPostFirstPtrs[opt] )
3076 {
3077 CURL_FORMFREE( RexxCURLData->HttpPostFirstPtrs[opt] );
3078 }
3079 RexxCURLData->HttpPostFirstPtrs[opt] = NULL;
3080 RexxCURLData->HttpPostLastPtrs[opt] = NULL;
3081 for ( i = 1; i <= sub_opt; i++ )
3082 {
3083 char *fd_name=NULL, *fd_value=NULL;
3084 if ( GetRexxVariable( RxPackageGlobalData, argv[2].strptr, &value, i ) == NULL )
3085 {
3086 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3087 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3088 }
3089 fd_name = value.strptr;
3090 for ( j = 0; j < value.strlength; j++ )
3091 {
3092 if ( value.strptr[j] == '=' )
3093 {
3094 value.strptr[j] = '\0';
3095 fd_value = &value.strptr[j+1];
3096 break;
3097 }
3098 }
3099 if ( fd_value == NULL )
3100 {
3101 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_STEM_VALUE, INTERR_STEM_VALUE_STRING );
3102 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3103 }
3104 InternalTrace( RxPackageGlobalData, "CurlSetopt(RXCURLOPT_POST_DATA)", "Variable: <%s%d> Name: <%s> Value: <%s>", argv[2].strptr, i, fd_name, fd_value );
3105 rc = curlformadd_rc = CURL_FORMADD( &RexxCURLData->HttpPostFirstPtrs[opt], &RexxCURLData->HttpPostLastPtrs[opt], CURLFORM_COPYNAME, fd_name, CURLFORM_COPYCONTENTS, fd_value, CURLFORM_CONTENTSLENGTH, strlen(fd_value), CURLFORM_END );
3106 /*
3107 * Free the memory allocated in GetRexxVariable()
3108 */
3109 FREE_TSD( RxPackageGlobalData, value.strptr );
3110 if ( curlformadd_rc != CURL_FORMADD_OK )
3111 {
3112 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3113 SetCURLError( RxPackageGlobalData, (CURLcode)curlformadd_rc, curl_formadd_errors[rc] );
3114 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3115 }
3116 }
3117 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->HttpPostFirstPtrs[opt] );
3118 if ( curl_rc != CURLE_OK )
3119 {
3120 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3121 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3122 break;
3123 }
3124 break;
3125 case RXCURLOPT_POST_FORM:
3126 /*
3127 * Always look for HTTPPOSTFORM option
3128 */
3129 opt = find_option( RxPackageGlobalData, "HTTPPOSTFORM", 12 );
3130 if ( opt == (-1) )
3131 {
3132 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, INTERR_INVALID_OPTION_STRING );
3133 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3134 }
3135 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->HttpPostFirstPtrs[opt] );
3136 if ( curl_rc != CURLE_OK )
3137 {
3138 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3139 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3140 break;
3141 }
3142 break;
3143 case RXCURLOPT_POST_FIELDS:
3144 /*
3145 * Check that arg[2] is a stem, then convert the stem into
3146 * a string of values
3147 */
3148 if ( argv[2].strlength
3149 && argv[2].strptr[argv[2].strlength-1] != '.' )
3150 {
3151 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3152 break;
3153 }
3154 /* can't do this on ooRexx 4.x as strptr is const argv[2].strptr[argv[2].strlength] = '\0'; */
3155 if ( GetRexxVariableInteger( RxPackageGlobalData, argv[2].strptr, &sub_opt, 0 ) == NULL )
3156 {
3157 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3158 break;
3159 }
3160 /*
3161 * Reset the string ptr if previously set
3162 */
3163 if ( RexxCURLData->StringPtrs[opt] )
3164 {
3165 free( RexxCURLData->StringPtrs[opt] );
3166 RexxCURLData->StringPtrs[opt] = NULL;
3167 }
3168 for ( i = 1; i <= sub_opt; i++ )
3169 {
3170 if ( GetRexxVariable( RxPackageGlobalData, argv[2].strptr, &value, i ) == NULL )
3171 {
3172 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3173 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3174 }
3175 if ( RexxCURLData->StringPtrs[opt] == NULL )
3176 {
3177 RexxCURLData->StringPtrs[opt] = (char *)malloc( value.strlength + 2 );
3178 if ( RexxCURLData->StringPtrs[opt] == NULL )
3179 {
3180 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3181 break;
3182 }
3183 strcpy( RexxCURLData->StringPtrs[opt], "" );
3184 tmp = RexxCURLData->StringPtrs[opt];
3185 }
3186 else
3187 {
3188 RexxCURLData->StringPtrs[opt] = (char *)realloc( RexxCURLData->StringPtrs[opt], strlen( RexxCURLData->StringPtrs[opt]) + value.strlength + 2 );
3189 if ( RexxCURLData->StringPtrs[opt] == NULL )
3190 {
3191 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3192 break;
3193 }
3194 }
3195 /*
3196 * Change of behaviour! The data should posted shold NOT be changed from what
3197 * the user specifies. To support previous versions, allow optional 3rd arg of
3198 * '&' to prepend '&' between stem values
3199 */
3200 if ( argc > 3
3201 && argv[3].strlength > 0 )
3202 {
3203 /* Concatenate argv[3].strptr and the new value to the previous string value
3204 * Don't prepend for first option
3205 */
3206 if ( i != 1 )
3207 {
3208 strcat( RexxCURLData->StringPtrs[opt], argv[3].strptr );
3209 count += argv[3].strlength;
3210 }
3211 }
3212 strcat( RexxCURLData->StringPtrs[opt], value.strptr );
3213 count += value.strlength;
3214 /*
3215 * Free the memory allocated in GetRexxVariable()
3216 */
3217 FREE_TSD( RxPackageGlobalData, value.strptr );
3218 }
3219 InternalTrace( RxPackageGlobalData, "CurlSetopt(RXCURLOPT_POST_FIELDS)", "Value: <%s> Length: %d", (RexxCURLData->StringPtrs[opt]) ? RexxCURLData->StringPtrs[opt] : "", count );
3220 /*
3221 * Set the length of the generated string...
3222 */
3223 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_POSTFIELDSIZE, count );
3224 if ( curl_rc != CURLE_OK )
3225 {
3226 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3227 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3228 break;
3229 }
3230 /*
3231 * Set the string
3232 */
3233 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, RexxCurlOptions[opt].number, RexxCURLData->StringPtrs[opt] );
3234 // rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_COPYPOSTFIELDS, RexxCURLData->StringPtrs[opt] );
3235 if ( curl_rc != CURLE_OK )
3236 {
3237 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3238 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3239 break;
3240 }
3241 break;
3242 case RXCURLOPT_OUTSTEM:
3243 /*
3244 * Check that arg[2] is a stem, then setup the write callback
3245 */
3246 if ( argv[2].strlength
3247 && argv[2].strptr[argv[2].strlength-1] != '.' )
3248 {
3249 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3250 break;
3251 }
3252 /*
3253 * Save the stem name for the write function...
3254 */
3255 if ( RexxCURLData->StringPtrs[opt] )
3256 free( RexxCURLData->StringPtrs[opt] );
3257 RexxCURLData->StringPtrs[opt] = (char *)malloc( argv[2].strlength + 1 );
3258 if ( RexxCURLData->StringPtrs[opt] == NULL )
3259 {
3260 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3261 break;
3262 }
3263 memcpy( RexxCURLData->StringPtrs[opt], argv[2].strptr, argv[2].strlength );
3264 RexxCURLData->StringPtrs[opt][argv[2].strlength] = '\0';
3265 /*
3266 * Set these globals to allow the write function to know which
3267 * compound variable to write.
3268 */
3269 RexxCURLData->outstem_index = opt;
3270 RexxCURLData->outstem_tail = 0;
3271 if ( RexxCURLData->outstem_strptr )
3272 free( RexxCURLData->outstem_strptr );
3273 RexxCURLData->outstem_strlength = 0;
3274 if ( RexxCURLData->outstem_line_terminator )
3275 free( RexxCURLData->outstem_line_terminator );
3276 RexxCURLData->outstem_line_terminator = 0;
3277 /*
3278 * If we have the optional line terminator (argument 3), allocate space here
3279 * and copy it. No terminator, default to LF (which was original terminator)
3280 */
3281 if ( argc == 4
3282 && argv[3].strlength )
3283 {
3284 ltlen = argv[3].strlength;
3285 ltstr = argv[3].strptr;
3286 }
3287 else
3288 {
3289 ltlen = strlen( eol );
3290 ltstr = eol;
3291 }
3292 RexxCURLData->outstem_line_terminator = malloc( ltlen + 1 );
3293 if ( RexxCURLData->outstem_line_terminator == NULL )
3294 {
3295 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3296 break;
3297 }
3298 strcpy( RexxCURLData->outstem_line_terminator, ltstr );
3299 /*
3300 * Set our write function to store the content
3301 */
3302 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_WRITEFUNCTION, &outstem_write_function );
3303 if ( curl_rc != CURLE_OK )
3304 {
3305 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3306 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3307 break;
3308 }
3309 break;
3310 case RXCURLOPT_HEADERSTEM:
3311 /*
3312 * Check that arg[2] is a stem, then setup the write callback
3313 */
3314 if ( argv[2].strlength
3315 && argv[2].strptr[argv[2].strlength-1] != '.' )
3316 {
3317 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3318 break;
3319 }
3320 /*
3321 * Save the stem name for the write function...
3322 */
3323 if ( RexxCURLData->StringPtrs[opt] )
3324 free( RexxCURLData->StringPtrs[opt] );
3325 RexxCURLData->StringPtrs[opt] = (char *)malloc( argv[2].strlength + 1 );
3326 if ( RexxCURLData->StringPtrs[opt] == NULL )
3327 {
3328 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3329 break;
3330 }
3331 memcpy( RexxCURLData->StringPtrs[opt], argv[2].strptr, argv[2].strlength );
3332 RexxCURLData->StringPtrs[opt][argv[2].strlength] = '\0';
3333 /*
3334 * Set these globals to allow the write function to know which
3335 * compound variable to write.
3336 */
3337 RexxCURLData->headerstem_index = opt;
3338 RexxCURLData->headerstem_tail = 0;
3339
3340 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_HEADERFUNCTION, &headerstem_write_function );
3341 if ( curl_rc != CURLE_OK )
3342 {
3343 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3344 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3345 break;
3346 }
3347 break;
3348 case RXCURLOPT_CALLBACK:
3349 if ( RexxCURLData->StringPtrs[opt] )
3350 free( RexxCURLData->StringPtrs[opt] );
3351 RexxCURLData->StringPtrs[opt] = (char *)malloc( argv[2].strlength + 1 );
3352 if ( RexxCURLData->StringPtrs[opt] == NULL )
3353 {
3354 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3355 break;
3356 }
3357 memcpy( RexxCURLData->StringPtrs[opt], argv[2].strptr, argv[2].strlength );
3358 RexxCURLData->StringPtrs[opt][argv[2].strlength] = '\0';
3359 /*
3360 * Do any extra processing here for some options
3361 */
3362 switch( RexxCurlOptions[opt].number )
3363 {
3364 case CURLOPT_PROGRESSFUNCTION:
3365 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_NOPROGRESS, 0 );
3366 if ( curl_rc != CURLE_OK )
3367 {
3368 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3369 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3370 break;
3371 }
3372 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_PROGRESSFUNCTION, &rexxcurl_progress_callback );
3373 if ( curl_rc != CURLE_OK )
3374 {
3375 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3376 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3377 break;
3378 }
3379 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_PROGRESSDATA, RxPackageGlobalData );
3380 if ( curl_rc != CURLE_OK )
3381 {
3382 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3383 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3384 break;
3385 }
3386 RexxCURLData->progress_index = opt;
3387 break;
3388 case CURLOPT_SSH_KEYFUNCTION:
3389 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_SSH_KEYFUNCTION, &rexxcurl_sshkey_callback );
3390 if ( curl_rc != CURLE_OK )
3391 {
3392 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3393 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3394 break;
3395 }
3396 rc = curl_rc = CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_SSH_KEYDATA, RxPackageGlobalData );
3397 if ( curl_rc != CURLE_OK )
3398 {
3399 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3400 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3401 break;
3402 }
3403 RexxCURLData->progress_index = opt;
3404 break;
3405 default:
3406 break;
3407 }
3408 break;
3409 default:
3410 /* error */
3411 break;
3412 }
3413 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3414 }
3415
rxfunc(CurlReset)3416 rxfunc( CurlReset )
3417 {
3418 ULONG rc = 0L;
3419 long curl;
3420 REXXCURLDATA *RexxCURLData;
3421 /*
3422 * Get thread-safe-data
3423 */
3424 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
3425 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
3426 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
3427
3428 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
3429 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
3430 if ( my_checkparam( RxPackageGlobalData, name, argc, 1, 1 ) )
3431 return( 1 );
3432 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
3433 {
3434 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
3435 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3436 }
3437 CURL_EASY_RESET( (CURL *)curl );
3438 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3439 }
3440
3441 /*
3442 * Equivalent of curl_formadd()
3443 * Args:
3444 * curl handle
3445 * option - COPYCONTENTS or FILECONTENTS
3446 * name of section
3447 * data for COPYCONTENTS or multiple content type/filename for FILECONTENTS
3448 *
3449 * call curlformadd curl, 'COPYCONTENTS', 'htmlcode', 'text/html', mydata
3450 * call curlformadd curl, 'FILE', 'moreimages', 'image/jpeg', 'pic1.jpg', , 'pic2.jpg'
3451 * content.1 = 'image/jpeg'; filename.1 = 'pic1.jpg'
3452 * content.2 = 'text/html' ; filename.2 = 'index.html'
3453 * content.2 = '' ; filename.2 = 'pic2.jpg'
3454 * content.0 = 3; filename.0 = 3
3455 * call curlformadd curl, 'FILE', 'imagesandhtml', 'content.', 'filename.'
3456 * call curlsetopt curl, 'HTTPPOSTFORM'
3457 * call curlperform curl
3458 * call curlformfree curl
3459
3460
3461 array:
3462 i=0 content.1 -> cf[0].option = CONTENTYTPE; cf[0].value = content.1
3463 i=0 filename.1 -> cf[1].option = CONTENTYTPE; cf[1].value = filename.1
3464 i=1 content.2 -> cf[2].option = CONTENTYTPE; cf[2].value = content.1
3465 i=1 filename.2 -> cf[3].option = CONTENTYTPE; cf[3].value = filename.1
3466 */
rxfunc(CurlFormAdd)3467 rxfunc( CurlFormAdd )
3468 {
3469 ULONG rc = 0L;
3470 long curl;
3471 int i,opt;
3472 CURLFORMcode curl_rc;
3473 int count,idx,num_buffers,contenttype;
3474 struct curl_forms *cf;
3475 RXSTRING *values;
3476 REXXCURLDATA *RexxCURLData;
3477 /*
3478 * Get thread-safe-data
3479 */
3480 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
3481 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
3482 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
3483
3484 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
3485 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
3486 if ( my_checkparam( RxPackageGlobalData, name, argc, 5, 0 ) )
3487 return( 1 );
3488 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
3489 {
3490 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
3491 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3492 }
3493 /*
3494 * Always look for HTTPPOSTFORM option
3495 */
3496 opt = find_option( RxPackageGlobalData, "HTTPPOSTFORM", 12 );
3497 if ( opt == (-1) )
3498 {
3499 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, INTERR_INVALID_OPTION_STRING );
3500 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3501 }
3502 if ( memcmpi( RxPackageGlobalData, "COPYCONTENTS", argv[1].strptr, argv[1].strlength ) == 0 )
3503 {
3504 if ( !RXVALIDSTRING( argv[2] ) )
3505 {
3506 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_MANDATORY_FIELD, INTERR_MANDATORY_FIELD_STRING );
3507 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3508 }
3509 InternalTrace( RxPackageGlobalData, "CurlFormAdd(COPYCONTENTS)", "Name: <%s> ContentType: <%s> Value: <%s>", argv[2].strptr, argv[3].strptr, argv[4].strptr );
3510 rc = curl_rc = CURL_FORMADD( &RexxCURLData->HttpPostFirstPtrs[opt],
3511 &RexxCURLData->HttpPostLastPtrs[opt],
3512 CURLFORM_COPYNAME,
3513 argv[2].strptr,
3514 CURLFORM_NAMELENGTH,
3515 argv[2].strlength,
3516 CURLFORM_CONTENTTYPE,
3517 argv[3].strptr,
3518 CURLFORM_COPYCONTENTS,
3519 argv[4].strptr,
3520 CURLFORM_CONTENTSLENGTH,
3521 argv[4].strlength,
3522 CURLFORM_END );
3523 if ( curl_rc != CURLE_OK )
3524 {
3525 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3526 SetCURLError( RxPackageGlobalData, (CURLcode)curl_rc, curl_formadd_errors[rc] );
3527 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3528 }
3529 }
3530 else if ( memcmpi( RxPackageGlobalData, "FILE", argv[1].strptr, argv[1].strlength ) == 0 )
3531 {
3532 /*
3533 * Check if we are using the array option
3534 */
3535 if ( argc == 5
3536 && argv[3].strptr[argv[3].strlength-1] == '.'
3537 && argv[4].strptr[argv[4].strlength-1] == '.' )
3538 {
3539 /*
3540 * arg[3] is array of contenttype, arg[4] is array of filenames
3541 */
3542 if ( GetRexxVariableInteger( RxPackageGlobalData, argv[3].strptr, &count, 0 ) == NULL )
3543 {
3544 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3545 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3546 }
3547 num_buffers = 1 + (count * 2);
3548 /*
3549 * Get an array of curl_forms structures; two for each stem item
3550 */
3551 cf = (struct curl_forms *)malloc( num_buffers*sizeof(struct curl_forms) );
3552 if ( cf == NULL )
3553 {
3554 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3555 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3556 }
3557 /*
3558 * Get an array of RXSTRINGs; one for each stem item
3559 */
3560 values = (RXSTRING *)malloc( count*sizeof(RXSTRING) );
3561 if ( values == NULL )
3562 {
3563 free( cf );
3564 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3565 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3566 }
3567
3568 for ( idx = 0, i = 0; i < count; i++ )
3569 {
3570 /*
3571 * Get the contenttype stem value
3572 */
3573 if ( GetRexxVariable( RxPackageGlobalData, argv[3].strptr, &values[i], i+1 ) == NULL )
3574 {
3575 free( cf );
3576 free( values );
3577 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3578 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3579 }
3580 /*
3581 * If the contenttype value is empty, do not add the option
3582 */
3583 if ( values[i].strlength )
3584 {
3585 cf[idx].value = values[i].strptr;
3586 cf[idx].option = CURLFORM_CONTENTTYPE;
3587 InternalTrace( RxPackageGlobalData, "CurlFormAdd", "Setting Contenttype %d Option %d Value: [%s](%d)",
3588 i, idx, cf[idx].value, cf[idx].option );
3589 idx++;
3590 }
3591 /*
3592 * Get the filename stem value
3593 */
3594 if ( GetRexxVariable( RxPackageGlobalData, argv[4].strptr, &values[i], i+1 ) == NULL )
3595 {
3596 free( cf );
3597 free( values );
3598 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3599 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3600 }
3601 cf[idx].option = CURLFORM_FILE;
3602 cf[idx].value = values[i].strptr;
3603 InternalTrace( RxPackageGlobalData, "CurlFormAdd", "Setting Filename %d Option %d Value: [%s](%d)",
3604 i, idx, cf[idx].value, cf[idx].option );
3605 idx++;
3606 }
3607 cf[idx].option = CURLFORM_END;
3608 cf[idx].value = NULL;
3609 InternalTrace( RxPackageGlobalData, "CurlFormAdd", "Executing curl_formadd. Name: [%s]%d",
3610 argv[2].strptr, argv[2].strlength );
3611 rc = curl_rc = CURL_FORMADD( &RexxCURLData->HttpPostFirstPtrs[opt],
3612 &RexxCURLData->HttpPostLastPtrs[opt],
3613 CURLFORM_COPYNAME,
3614 argv[2].strptr,
3615 CURLFORM_NAMELENGTH,
3616 argv[2].strlength,
3617 CURLFORM_ARRAY,
3618 cf,
3619 CURLFORM_END );
3620 /*
3621 * Free the memory allocated in GetRexxVariable()
3622 */
3623 for ( i = 0 ; i < count ; i++ )
3624 {
3625 FREE_TSD( RxPackageGlobalData, values[i].strptr );
3626 }
3627 free( cf );
3628 if ( curl_rc != CURLE_OK )
3629 {
3630 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3631 SetCURLError( RxPackageGlobalData, (CURLcode)curl_rc, curl_formadd_errors[rc] );
3632 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3633 }
3634 }
3635 else
3636 {
3637 /*
3638 * We can have any number of pairs of options after the 3rd mandatory option
3639 */
3640 if ( argc % 2 == 0 )
3641 {
3642 return 1;
3643 }
3644 /*
3645 * Number of file pairs
3646 */
3647 count = ( argc - 3 ) / 2;
3648 num_buffers = 1 + (count * 2);
3649 /*
3650 * Get an array of curl_forms structures; one for each stem item
3651 */
3652 cf = (struct curl_forms *)malloc( num_buffers*sizeof(struct curl_forms) );
3653 if ( cf == NULL )
3654 {
3655 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3656 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3657 }
3658 /*
3659 * Get an array of RXSTRINGs; one for each stem item
3660 */
3661 values = (RXSTRING *)malloc( count*sizeof(RXSTRING) );
3662 if ( values == NULL )
3663 {
3664 free( cf );
3665 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
3666 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3667 }
3668 contenttype = 1;
3669 for ( idx = 0, i = 3; i < argc; i++ )
3670 {
3671 /*
3672 * If the contenttype value is empty, do not add the option
3673 */
3674 if ( contenttype )
3675 {
3676 if ( RXVALIDSTRING( argv[i] ) )
3677 {
3678 cf[idx].value = argv[i].strptr;
3679 cf[idx].option = CURLFORM_CONTENTTYPE;
3680 InternalTrace( RxPackageGlobalData, "CurlFormAdd", "Setting Contenttype %d Option %d Value: [%s](%d)",
3681 i, idx, cf[idx].value, cf[idx].option );
3682 idx++;
3683 }
3684 contenttype = 0;
3685 }
3686 else
3687 {
3688 cf[idx].option = CURLFORM_FILE;
3689 cf[idx].value = argv[i].strptr;
3690 InternalTrace( RxPackageGlobalData, "CurlFormAdd", "Setting Filename %d Option %d Value: [%s](%d)",
3691 i, idx, cf[idx].value, cf[idx].option );
3692 idx++;
3693 contenttype = 1;
3694 }
3695 }
3696 cf[idx].option = CURLFORM_END;
3697 cf[idx].value = NULL;
3698 InternalTrace( RxPackageGlobalData, "CurlFormAdd", "Executing curl_formadd. Name: [%s]%d",
3699 argv[2].strptr, argv[2].strlength );
3700 rc = curl_rc = CURL_FORMADD( &RexxCURLData->HttpPostFirstPtrs[opt],
3701 &RexxCURLData->HttpPostLastPtrs[opt],
3702 CURLFORM_COPYNAME,
3703 argv[2].strptr,
3704 CURLFORM_NAMELENGTH,
3705 argv[2].strlength,
3706 CURLFORM_ARRAY,
3707 cf,
3708 CURLFORM_END );
3709 /*
3710 * Free the memory allocated in GetRexxVariable()
3711 */
3712 for ( i = 0 ; i < count ; i++ )
3713 {
3714 FREE_TSD( RxPackageGlobalData, values[i].strptr );
3715 }
3716 free( cf );
3717 if ( curl_rc != CURLE_OK )
3718 {
3719 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3720 SetCURLError( RxPackageGlobalData, (CURLcode)curl_rc, curl_formadd_errors[rc] );
3721 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3722 }
3723 }
3724 }
3725 else
3726 {
3727 char buf[1024];
3728 sprintf( buf, "%s: %s", INTERR_INVALID_OPTION_STRING, argv[1].strptr );
3729 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, buf );
3730 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3731 }
3732 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3733 }
3734
rxfunc(CurlPerform)3735 rxfunc( CurlPerform )
3736 {
3737 long curl;
3738 CURLcode rc;
3739 char value[20]; /* big enough for an int */
3740 int valuelen,i;
3741 REXXCURLDATA *RexxCURLData;
3742 /*
3743 * Get thread-safe-data
3744 */
3745 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
3746 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
3747 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
3748
3749 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
3750 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
3751 if ( my_checkparam( RxPackageGlobalData, name, argc, 1, 1 ) )
3752 return( 1 );
3753 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
3754 {
3755 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
3756 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3757 }
3758 /*
3759 * Set the CURLOPT_ERRORBUFFER here to ensure we get a string
3760 * error if something goes wrong.
3761 */
3762 strcpy( RexxCURLData->curl_error, "" );
3763 CURL_EASY_SETOPT( (CURL *)curl, CURLOPT_ERRORBUFFER, RexxCURLData->curl_error );
3764 InternalTrace( RxPackageGlobalData, "CurlPerform", "Set ERRORBUFFER OK" );
3765 RexxCURLData->g_curl_error = rc = CURL_EASY_PERFORM( (CURL *)curl );
3766 if ( rc != 0 )
3767 {
3768 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3769 SetCURLError( RxPackageGlobalData, rc, (char *)RexxCURLData->curl_error );
3770 }
3771 InternalTrace( RxPackageGlobalData, "CurlPerform", "curl_easy_perform exited with %d", rc );
3772 /*
3773 * For those options that return their data in a stem, we need to set
3774 * the stem.0 value to the number of stem variables actually created.
3775 */
3776 if ( RexxCURLData->outstem_index )
3777 {
3778 InternalTrace( RxPackageGlobalData, "CurlPerform", "Using OUTSTEM" );
3779 outstem_create( RxPackageGlobalData );
3780 valuelen = sprintf( value, "%d", RexxCURLData->outstem_tail );
3781 create_rexx_compound( RxPackageGlobalData, RexxCURLData->StringPtrs[RexxCURLData->outstem_index], 0, value, valuelen );
3782 RexxCURLData->outstem_index = RexxCURLData->outstem_tail = RexxCURLData->outstem_strlength = 0;
3783 if ( RexxCURLData->outstem_strptr )
3784 {
3785 free( RexxCURLData->outstem_strptr );
3786 RexxCURLData->outstem_strptr = NULL;
3787 RexxCURLData->outstem_strlength = 0;
3788 }
3789 if ( RexxCURLData->outstem_line_terminator )
3790 {
3791 free( RexxCURLData->outstem_line_terminator );
3792 RexxCURLData->outstem_line_terminator = NULL;
3793 }
3794 }
3795 if ( RexxCURLData->headerstem_index )
3796 {
3797 InternalTrace( RxPackageGlobalData, "CurlPerform", "Using HEADERSTEM" );
3798 valuelen = sprintf( value, "%d", RexxCURLData->headerstem_tail );
3799 create_rexx_compound( RxPackageGlobalData, RexxCURLData->StringPtrs[RexxCURLData->headerstem_index], 0, value, valuelen );
3800 RexxCURLData->headerstem_index = RexxCURLData->headerstem_tail = 0;
3801 }
3802 /*
3803 * If OUTFILE or INFILE is used, close it here and set the FILE * to NULL
3804 */
3805 for ( i = 0; i < NUMBER_REXXCURL_OPTIONS; i++ )
3806 {
3807 if ( ( RexxCurlOptions[i].optiontype == RXCURLOPT_OUTFILE
3808 || RexxCurlOptions[i].optiontype == RXCURLOPT_INFILE )
3809 && RexxCURLData->FilePtrs[i] )
3810 {
3811 fclose( RexxCURLData->FilePtrs[i] );
3812 RexxCURLData->FilePtrs[i] = NULL;
3813 }
3814 }
3815 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3816 }
3817
rxfunc(CurlGetinfo)3818 rxfunc( CurlGetinfo )
3819 {
3820 ULONG rc = 0L;
3821 CURLcode curl_rc;
3822 long curl;
3823 int opt,suboption;
3824 int idx = 0;
3825 char *return_string = NULL;
3826 double return_double;
3827 long return_long;
3828 struct curl_slist *TmpSListPtrs = NULL;
3829 struct curl_slist *OrigSListPtrs=NULL;
3830 #if LIBCURL_VERSION_NUM >= 0x071301
3831 struct curl_certinfo *TmpCertInfoPtrs = NULL;
3832 #endif
3833 char value[20]; /* big enough for an int */
3834 int valuelen,i;
3835 REXXCURLDATA *RexxCURLData;
3836 /*
3837 * Get thread-safe-data
3838 */
3839 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
3840 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
3841 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
3842
3843 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
3844 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
3845 if ( my_checkparam( RxPackageGlobalData, name, argc, 2, 3 ) )
3846 return( 1 );
3847 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
3848 {
3849 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
3850 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3851 }
3852 opt = find_getinfo( RxPackageGlobalData, argv[1].strptr, argv[1].strlength );
3853 if ( opt == (-1) )
3854 {
3855 char buf[1024];
3856 sprintf( buf, "%s: %s", INTERR_INVALID_OPTION_STRING, argv[1].strptr );
3857 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, buf );
3858 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
3859 }
3860 switch( RexxCurlGetinfos[opt].optiontype )
3861 {
3862 case RXCURLINFO_STRING:
3863 rc = curl_rc = CURL_EASY_GETINFO( (CURL *)curl, RexxCurlGetinfos[opt].number, &return_string );
3864 if ( curl_rc != CURLE_OK )
3865 {
3866 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3867 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3868 break;
3869 }
3870 return RxReturnString( RxPackageGlobalData, retstr, return_string );
3871 break;
3872 case RXCURLINFO_DOUBLE:
3873 rc = curl_rc = CURL_EASY_GETINFO( (CURL *)curl, RexxCurlGetinfos[opt].number, &return_double );
3874 if ( curl_rc != CURLE_OK )
3875 {
3876 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3877 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3878 break;
3879 }
3880 return RxReturnDouble( RxPackageGlobalData, retstr, return_double );
3881 break;
3882 case RXCURLINFO_LONG:
3883 rc = curl_rc = CURL_EASY_GETINFO( (CURL *)curl, RexxCurlGetinfos[opt].number, &return_long );
3884 if ( curl_rc != CURLE_OK )
3885 {
3886 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3887 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3888 break;
3889 }
3890 return RxReturnNumber( RxPackageGlobalData, retstr, return_long );
3891 break;
3892 case RXCURLINFO_LIST:
3893 if ( argc != 3 )
3894 {
3895 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_TOO_FEW_ARGS, INTERR_TOO_FEW_ARGS_STRING );
3896 break;
3897 }
3898 /*
3899 * Check that we have a stem
3900 */
3901 if ( argv[2].strptr[argv[2].strlength-1] != '.' )
3902 {
3903 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3904 break;
3905 }
3906 rc = curl_rc = CURL_EASY_GETINFO( (CURL *)curl, RexxCurlGetinfos[opt].number, &TmpSListPtrs );
3907 if ( curl_rc != CURLE_OK )
3908 {
3909 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3910 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3911 break;
3912 }
3913 OrigSListPtrs = TmpSListPtrs;
3914 for ( i = 1; TmpSListPtrs; i++, TmpSListPtrs=TmpSListPtrs->next )
3915 {
3916 create_rexx_compound( RxPackageGlobalData, argv[2].strptr, i, TmpSListPtrs->data, strlen( TmpSListPtrs->data ) );
3917 }
3918 valuelen = sprintf( value, "%d", i-1 );
3919 create_rexx_compound( RxPackageGlobalData, argv[2].strptr, 0, value, valuelen );
3920 if ( OrigSListPtrs )
3921 {
3922 CURL_SLIST_FREE_ALL( OrigSListPtrs );
3923 }
3924 return RxReturnNumber( RxPackageGlobalData, retstr, i-1 );
3925 break;
3926 #if LIBCURL_VERSION_NUM >= 0x071301
3927 case RXCURLINFO_CERTINFO:
3928 if ( argc != 3 )
3929 {
3930 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_TOO_FEW_ARGS, INTERR_TOO_FEW_ARGS_STRING );
3931 break;
3932 }
3933 /*
3934 * Check that we have a stem
3935 */
3936 if ( argv[2].strptr[argv[2].strlength-1] != '.' )
3937 {
3938 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_STEM, INTERR_INVALID_STEM_STRING );
3939 break;
3940 }
3941 rc = curl_rc = CURL_EASY_GETINFO( (CURL *)curl, RexxCurlGetinfos[opt].number, &TmpCertInfoPtrs );
3942 if ( curl_rc != CURLE_OK )
3943 {
3944 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3945 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3946 break;
3947 }
3948 if ( TmpCertInfoPtrs )
3949 {
3950 for ( i = 0; i < TmpCertInfoPtrs->num_of_certs; i++ )
3951 {
3952 TmpSListPtrs = TmpCertInfoPtrs->certinfo[i];
3953 for ( ; TmpSListPtrs; TmpSListPtrs=TmpSListPtrs->next )
3954 {
3955 idx++;
3956 create_rexx_compound( RxPackageGlobalData, argv[2].strptr, idx, TmpSListPtrs->data, strlen( TmpSListPtrs->data ) );
3957 }
3958 /* don't free the slist!! */
3959 }
3960 }
3961 valuelen = sprintf( value, "%d", idx );
3962 create_rexx_compound( RxPackageGlobalData, argv[2].strptr, 0, value, valuelen );
3963 /* don't free the TmpCertInfoPtrs */
3964 return RxReturnNumber( RxPackageGlobalData, retstr, idx );
3965 break;
3966 #endif
3967 case RXCURLINFO_BITMAP:
3968 suboption = 0;
3969 rc = curl_rc = CURL_EASY_GETINFO( (CURL *)curl, RexxCurlGetinfos[opt].number, &return_long );
3970 if ( curl_rc != CURLE_OK )
3971 {
3972 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_CURL_ERROR, INTERR_CURL_ERROR_STRING );
3973 SetCURLError( RxPackageGlobalData, curl_rc, curl_errors[rc] );
3974 break;
3975 }
3976 switch( RexxCurlGetinfos[opt].number )
3977 {
3978 #if LIBCURL_VERSION_NUM >= 0x070a08
3979 case CURLINFO_HTTPAUTH_AVAIL:
3980 case CURLINFO_PROXYAUTH_AVAIL:
3981 suboption = RXCURLOPT_BITMAP_AUTH;
3982 break;
3983 #endif
3984 default:
3985 break;
3986 }
3987 if ( suboption != 0 )
3988 {
3989 valuelen = 0;
3990 /*
3991 * Get the total length of our return string
3992 */
3993 for ( idx = 0; RexxCurlSubOptions[idx].name != NULL; idx++ )
3994 {
3995 if ( RexxCurlSubOptions[idx].optiontype == suboption
3996 && RexxCurlSubOptions[idx].newname == NULL
3997 && ( RexxCurlSubOptions[idx].number & return_long ) == RexxCurlSubOptions[idx].number )
3998 valuelen = valuelen + 1 + strlen( RexxCurlSubOptions[idx].name );
3999 }
4000 /* allocate our return string */
4001 return_string = RexxAllocateMemory( valuelen + 1 );
4002 if ( return_string == NULL )
4003 {
4004 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
4005 break;
4006 }
4007 /*
4008 * Append each value to our return string
4009 */
4010 strcpy( return_string, "" );
4011 for ( idx = 0; RexxCurlSubOptions[idx].name != NULL; idx++ )
4012 {
4013 if ( RexxCurlSubOptions[idx].optiontype == suboption
4014 && RexxCurlSubOptions[idx].newname == NULL
4015 && ( RexxCurlSubOptions[idx].number & return_long ) == RexxCurlSubOptions[idx].number )
4016 {
4017 strcat( return_string, RexxCurlSubOptions[idx].name );
4018 strcat( return_string, " " );
4019 }
4020 }
4021 return RxReturnStringAndFree( RxPackageGlobalData, retstr, return_string, 1 );
4022 }
4023 break;
4024 default:
4025 /* error */
4026 break;
4027 }
4028 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4029 }
4030
rxfunc(CurlFormFree)4031 rxfunc( CurlFormFree )
4032 {
4033 long curl;
4034 int opt;
4035 REXXCURLDATA *RexxCURLData;
4036 /*
4037 * Get thread-safe-data
4038 */
4039 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
4040 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
4041 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
4042
4043 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
4044 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
4045 if ( my_checkparam( RxPackageGlobalData, name, argc, 1, 1 ) )
4046 return( 1 );
4047 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
4048 {
4049 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
4050 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4051 }
4052 /*
4053 * Always look for HTTPPOSTFORM option
4054 */
4055 opt = find_option( RxPackageGlobalData, "HTTPPOSTFORM", 12 );
4056 if ( opt == (-1) )
4057 {
4058 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_OPTION, INTERR_INVALID_OPTION_STRING );
4059 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4060 }
4061 if ( RexxCURLData->HttpPostFirstPtrs[opt] )
4062 {
4063 CURL_FORMFREE( RexxCURLData->HttpPostFirstPtrs[opt] );
4064 }
4065 RexxCURLData->HttpPostFirstPtrs[opt] = NULL;
4066 RexxCURLData->HttpPostLastPtrs[opt] = NULL;
4067 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4068 }
4069
rxfunc(CurlEscape)4070 rxfunc( CurlEscape )
4071 {
4072 long curl;
4073 int valuelen;
4074 char *url, *return_string;
4075 REXXCURLDATA *RexxCURLData;
4076 /*
4077 * Get thread-safe-data
4078 */
4079 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
4080 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
4081 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
4082
4083 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
4084 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
4085 if ( my_checkparam( RxPackageGlobalData, name, argc, 2, 2 ) )
4086 return( 1 );
4087 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
4088 {
4089 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
4090 return RxReturnNumber( RxPackageGlobalData, retstr, INTERR_INVALID_HANDLE ) ;
4091 }
4092
4093 url = CURL_EASY_ESCAPE( (CURL *)curl, (char *)RXSTRPTR( argv[1] ), RXSTRLEN( argv[1] ) );
4094 if ( url == NULL )
4095 {
4096 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
4097 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4098 }
4099 valuelen = strlen( url );
4100 return_string = RexxAllocateMemory( valuelen + 1 );
4101 if ( return_string == NULL )
4102 {
4103 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
4104 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4105 }
4106 strcpy( return_string, url );
4107 CURL_FREE( url );
4108 return RxReturnStringAndFree( RxPackageGlobalData, retstr, return_string, 1 ) ;
4109 }
4110
rxfunc(CurlUnescape)4111 rxfunc( CurlUnescape )
4112 {
4113 long curl;
4114 int valuelen;
4115 char *url, *return_string;
4116 REXXCURLDATA *RexxCURLData;
4117 /*
4118 * Get thread-safe-data
4119 */
4120 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
4121 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
4122 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
4123
4124 if ( RexxCURLData->g_curl_error) ClearCURLError( RxPackageGlobalData );
4125 if ( RexxCURLData->g_rexxcurl_error) ClearIntError( RxPackageGlobalData );
4126 if ( my_checkparam( RxPackageGlobalData, name, argc, 2, 2 ) )
4127 return( 1 );
4128 if ( RxStrToLong( RxPackageGlobalData, &argv[0], &curl ) != 0 )
4129 {
4130 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_HANDLE, INTERR_INVALID_HANDLE_STRING );
4131 return RxReturnNumber( RxPackageGlobalData, retstr, INTERR_INVALID_HANDLE ) ;
4132 }
4133
4134 url = CURL_EASY_UNESCAPE( (CURL *)curl, (char *)RXSTRPTR( argv[1] ), RXSTRLEN( argv[1] ), &valuelen );
4135 if ( url == NULL )
4136 {
4137 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
4138 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4139 }
4140 return_string = RexxAllocateMemory( valuelen + 1 );
4141 if ( return_string == NULL )
4142 {
4143 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_NO_MEMORY, INTERR_NO_MEMORY_STRING );
4144 return RxReturnString( RxPackageGlobalData, retstr, "" ) ;
4145 }
4146 strcpy( return_string, url );
4147 CURL_FREE( url );
4148 return RxReturnStringAndFree( RxPackageGlobalData, retstr, return_string, 1 ) ;
4149 }
4150
4151 /*
4152 * If an argument is passed, check if it is a valid function name
4153 * If no argument is passed, return all function names
4154 * Curlqueryfunction( var|stem, opt )
4155 * opt is R(registered), A(vailable)
4156 *
4157 * return 0 is successful - stem or func found
4158 * return 1 if func not found
4159 */
rxfunc(CurlQueryFunction)4160 rxfunc(CurlQueryFunction)
4161 {
4162 ULONG rc = 0L;
4163 int i,len,tmplen,idx;
4164 char *stem;
4165 char optionchar;
4166 char varname[255], value[10];
4167 char stem_name[255];
4168 REXXCURLDATA *RexxCURLData;
4169 /*
4170 * Get thread-safe-data
4171 */
4172 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
4173 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
4174 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
4175
4176 if ( my_checkparam( RxPackageGlobalData, name, argc, 1, 2 ) )
4177 return( 1 );
4178
4179 stem = RXSTRPTR(argv[0]);
4180 len = RXSTRLEN(argv[0]);
4181
4182 if ( argc == 1 )
4183 optionchar = 'R';
4184 else
4185 optionchar = toupper( *argv[1].strptr );
4186
4187 if ( stem[len-1] != '.' )
4188 {
4189 /*
4190 * Check that the specified function name is available/registered
4191 */
4192 rc = 1L; /* not found by default */
4193 for ( i = 0; RexxCURLFunctions[i].ExternalName != NULL; i++ )
4194 {
4195 tmplen = strlen( (char *)RexxCURLFunctions[i].ExternalName );
4196 if ( tmplen == len
4197 && memcmpi( RxPackageGlobalData, (char *)RexxCURLFunctions[i].ExternalName, stem, len ) == 0 )
4198 {
4199 /*
4200 * Function is available...
4201 */
4202 rc = 0L;
4203 if ( RexxQueryFunction( RexxCURLFunctions[i].InternalName )
4204 && optionchar == 'R' )
4205 {
4206 /*
4207 * Function is not registered and we wanted a registered function
4208 */
4209 rc = 1L;
4210 }
4211 break;
4212 }
4213 }
4214 }
4215 else
4216 {
4217 strcpy( stem_name, stem );
4218 make_upper( RxPackageGlobalData, stem_name );
4219 idx = 0;
4220 for ( i = 0; RexxCURLFunctions[i].ExternalName != NULL; i++ )
4221 {
4222 if ( RexxQueryFunction( RexxCURLFunctions[i].InternalName )
4223 && optionchar == 'R' )
4224 {
4225 /*
4226 * Function is not registered, and we wanted only registered functions
4227 */
4228 ;
4229 }
4230 else
4231 {
4232 idx++;
4233 len = sprintf( varname, "%s%u", stem_name, idx );
4234 if ( SetRexxVariable( RxPackageGlobalData, varname, len, (char *)RexxCURLFunctions[i].ExternalName, strlen( RexxCURLFunctions[i].ExternalName ) ) == 1 )
4235 return(1);
4236 }
4237 }
4238 i = sprintf( value, "%u", idx);
4239 len = sprintf(varname, "%s0", stem_name);
4240 rc = SetRexxVariable( RxPackageGlobalData, varname, len, value, i );
4241 }
4242 return RxReturnNumber( NULL, retstr, rc );
4243 }
4244
rxfunc(CurlVariable)4245 rxfunc( CurlVariable )
4246 {
4247 RX_ULONG rc = 0L;
4248 char buf[250];
4249 REXXCURLDATA *RexxCURLData;
4250 /*
4251 * Get thread-safe-data
4252 */
4253 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
4254
4255 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
4256
4257 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
4258
4259 if ( my_checkparam( RxPackageGlobalData, (char *)name, argc, 1, 2 ) )
4260 return( 1 );
4261 if ( RXSTRLEN( argv[0] ) == 9 && memcmpi( RxPackageGlobalData, "DEBUGFILE", RXSTRPTR( argv[0] ), RXSTRLEN( argv[0] ) ) == 0 )
4262 {
4263 if ( argc == 1 )
4264 return RxReturnString( RxPackageGlobalData, retstr, RxGetTraceFile( RxPackageGlobalData ) );
4265 else
4266 {
4267 rc = RxSetTraceFile( RxPackageGlobalData, (char *)RXSTRPTR( argv[1] ) );
4268 return RxReturnNumber( RxPackageGlobalData, retstr, rc );
4269 }
4270 }
4271 else if ( RXSTRLEN( argv[0] ) == 5 && memcmpi( RxPackageGlobalData, "DEBUG", RXSTRPTR( argv[0] ), RXSTRLEN( argv[0] ) ) == 0 )
4272 {
4273 if ( argc == 1 )
4274 {
4275 sprintf( buf, "%d", RxGetRunFlags( RxPackageGlobalData ) );
4276 return RxReturnString( RxPackageGlobalData, retstr, buf );
4277 }
4278 else
4279 {
4280 if ( RxStrToULong( RxPackageGlobalData, &argv[1], (RX_ULONG *)&rc ) == -1 )
4281 return RxReturnString( RxPackageGlobalData, retstr, "ERROR: Invalid DEBUG value. Cannot set variable; DEBUG" );
4282 RxSetRunFlags ( RxPackageGlobalData, rc );
4283 return RxReturnNumber( RxPackageGlobalData, retstr, 0 );
4284 }
4285 }
4286 else if ( RXSTRLEN( argv[0] ) == 7 && memcmpi( RxPackageGlobalData, "VERSION", RXSTRPTR( argv[0] ), RXSTRLEN( argv[0] ) ) == 0 )
4287 {
4288 if ( argc == 1 )
4289 {
4290 sprintf( buf, "%s %s %s %s", RxPackageName, REXXCURL_VERSION, REXXCURL_DATE, CURL_VERSION() );
4291 return RxReturnString( RxPackageGlobalData, retstr, buf );
4292 }
4293 else
4294 return RxReturnString( RxPackageGlobalData, retstr, "ERROR: Cannot set variable; VERSION" );
4295 }
4296 else if ( RXSTRLEN( argv[0] ) == 5 && memcmpi( RxPackageGlobalData, "ERROR", RXSTRPTR( argv[0] ), RXSTRLEN( argv[0] ) ) == 0 )
4297 {
4298 if ( argc == 1 )
4299 {
4300 return RxReturnString( RxPackageGlobalData, retstr, RexxCURLData->rexxcurl_error_prefix );
4301 }
4302 else
4303 {
4304 memcpy( RexxCURLData->rexxcurl_error_prefix, argv[1].strptr, argv[1].strlength );
4305 RexxCURLData->rexxcurl_error_prefix[argv[1].strlength] = '\0';
4306 return RxReturnString( RxPackageGlobalData, retstr, "" );
4307 }
4308 }
4309 else if ( RXSTRLEN(argv[0]) == 14 && memcmpi( RxPackageGlobalData, "CONSTANTPREFIX", RXSTRPTR(argv[0]), RXSTRLEN(argv[0]) ) == 0 )
4310 {
4311 if ( argc == 1 )
4312 {
4313 return RxReturnString( RxPackageGlobalData, retstr, RxGetConstantPrefix( RxPackageGlobalData ) );
4314 }
4315 else
4316 {
4317 rc = RxSetConstantPrefix( RxPackageGlobalData, (char *)argv[1].strptr );
4318 /*
4319 * Now we have a new prefix, we should reset all our constants...
4320 */
4321 SetPackageConstants( RxPackageGlobalData, RexxCURLConstants, 1 );
4322 /*
4323 * ...and our version info variables
4324 */
4325 RexxCURLSetVersionInfoConstants( RxPackageGlobalData );
4326 return RxReturnNumber( RxPackageGlobalData, retstr, rc );
4327 }
4328 }
4329 sprintf( buf, "%s %s", INTERR_INVALID_VARIABLE_STRING, argv[0].strptr );
4330 SetIntError( RxPackageGlobalData, __FILE__, __LINE__, INTERR_INVALID_VARIABLE, buf );
4331 return RxReturnString( RxPackageGlobalData, retstr, "" );
4332 }
4333
4334 /*====== Routines for handling registration of functions ======*/
4335
4336
rxfunc(CurlLoadFuncs)4337 rxfunc( CurlLoadFuncs )
4338 {
4339 int rc = 0L;
4340
4341 /*
4342 * Get thread-safe-data for DLL. EXE global data is not thread-safe
4343 */
4344 RxPackageGlobalDataDef *RxPackageGlobalData = GLOBAL_ENTRY_POINT();
4345 InitRxPackage( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, &rc );
4346 if ( !QueryRxFunction( RxPackageGlobalData, "CURLINIT" ) )
4347 {
4348 /*
4349 * Register all external functions
4350 */
4351 if ( !rc )
4352 {
4353 rc = RegisterRxFunctions( RxPackageGlobalData, RexxCURLFunctions, RxPackageName );
4354 }
4355 }
4356 rc = RexxCURLInitHandler( 0, 0, NULL );
4357 return RxReturnNumber( RxPackageGlobalData, retstr, rc );
4358 }
4359
rxfunc(CurlDropFuncs)4360 rxfunc( CurlDropFuncs )
4361 {
4362 int rc=0;
4363 int unload=0;
4364 REXXCURLDATA *RexxCURLData;
4365 /*
4366 * Get thread-safe-data
4367 */
4368 RxPackageGlobalDataDef *RxPackageGlobalData = __rxpack_get_tsd();
4369
4370 RxPackageGlobalData = FunctionPrologue( RxPackageGlobalData, RexxCURLInitialiser, RXPACKAGE_CONSTANT_PREFIX, (char*)name, argc, argv );
4371
4372 RexxCURLData=(REXXCURLDATA *)RxPackageGlobalData->RXPACKAGE_tsd;
4373
4374 if ( my_checkparam( RxPackageGlobalData, (char *)name, argc, 0, 1 ) )
4375 return( 1 );
4376 if ( argv[0].strlength == 6
4377 && memcmpi( RxPackageGlobalData, argv[0].strptr, "UNLOAD", 6 ) == 0 )
4378 unload = 1;
4379 (void)TermRxPackage( RxPackageGlobalData, RexxCURLTerminator, RexxCURLFunctions, RxPackageName, unload );
4380 return RxReturnNumber( NULL, retstr, rc );
4381 }
4382
4383
4384
4385 /*
4386 * The following functions are used in rxpackage.c
4387 */
4388
4389 /*-----------------------------------------------------------------------------
4390 * Print a usage message.
4391 *----------------------------------------------------------------------------*/
RexxCURLUsage(void)4392 void RexxCURLUsage
4393
4394 #ifdef HAVE_PROTO
4395 (void)
4396 #else
4397 ()
4398 #endif
4399
4400 {
4401 char buf[1024];
4402 (void)fprintf(stderr,
4403 "\nVersion: %s %s %s\nUsing: %s\n\nUsage: %s [-h]\n %s [-idvf<trace file>] [Rexx program name]\n\n",
4404 RxPackageName,
4405 REXXCURL_VERSION,
4406 REXXCURL_DATE,
4407 RxGetRexxInterpreterVersion( buf ),
4408 RxPackageName,
4409 RxPackageName);
4410 }
4411
4412
4413 #if defined(USE_REXX6000)
4414 /*
4415 * This function is used as the entry point for the REXX/6000
4416 * interpreter
4417 * If you change this table, don't forget to change the table at the
4418 * start of this file.
4419 */
InitFunc(RXFUNCBLOCK ** FuncBlock)4420 USHORT InitFunc( RXFUNCBLOCK **FuncBlock )
4421 {
4422 static RXFUNCBLOCK funcarray[] =
4423 {
4424 { NULL, NULL, NULL }
4425 } ;
4426 *FuncBlock = funcarray;
4427 return (USHORT)0;
4428 }
4429 #endif
4430