diff options
author | Patrick Monnerat <patrick@monnerat.net> | 2023-04-18 16:34:04 +0200 |
---|---|---|
committer | Jay Satiro <raysatiro@yahoo.com> | 2023-04-18 16:13:56 -0400 |
commit | a1fa2b30c0ce300addd0a18c665b2007ee782c7c (patch) | |
tree | 20cfcd1dfd2019a8cf7c5fc916d1faabce5a55a9 /packages/OS400 | |
parent | b98db942676414e97573016685625e1519927f4c (diff) | |
download | curl-a1fa2b30c0ce300addd0a18c665b2007ee782c7c.tar.gz |
OS400: implement EBCDIC support for recent features
- Support CURLVERSION_ELEVENTH.
- New function curl_url_strerror_ccsid().
- curl_easy_setopt_ccsid() supports blobs and 3 recent string options.
- New function curl_easy_header_ccsid().
- New generic latin1<-->ccsid conversion functions curl_from_ccsid() and
curl_to_ccsid() for user convenience.
- README.OS400 updated accordingly.
- Removed a leftover QsoSSL support identifier.
Closes https://github.com/curl/curl/pull/10994
Diffstat (limited to 'packages/OS400')
-rw-r--r-- | packages/OS400/README.OS400 | 42 | ||||
-rw-r--r-- | packages/OS400/ccsidcurl.c | 204 | ||||
-rw-r--r-- | packages/OS400/ccsidcurl.h | 9 | ||||
-rw-r--r-- | packages/OS400/os400sys.h | 2 |
4 files changed, 163 insertions, 94 deletions
diff --git a/packages/OS400/README.OS400 b/packages/OS400/README.OS400 index e245aff99..b1b8f0e2d 100644 --- a/packages/OS400/README.OS400 +++ b/packages/OS400/README.OS400 @@ -1,8 +1,8 @@ Implementation notes: - This is a true OS/400 implementation, not a PASE implementation (for PASE, -use AIX implementation). + This is a true OS/400 ILE implementation, not a PASE implementation (for +PASE, use AIX implementation). The biggest problem with OS/400 is EBCDIC. Libcurl implements an internal conversion mechanism, but it has been designed for computers that have a @@ -96,6 +96,7 @@ options: CURLOPT_PASSWORD CURLOPT_PINNEDPUBLICKEY CURLOPT_PRE_PROXY + CURLOPT_PROTOCOLS_STR CURLOPT_PROXY CURLOPT_PROXYPASSWORD CURLOPT_PROXYUSERNAME @@ -117,6 +118,7 @@ options: CURLOPT_PROXY_TLSAUTH_USERNAME CURLOPT_RANDOM_FILE CURLOPT_RANGE + CURLOPT_REDIR_PROTOCOLS_STR CURLOPT_REFERER CURLOPT_REQUEST_TARGET CURLOPT_RTSP_SESSION_UID @@ -126,6 +128,7 @@ options: CURLOPT_SERVICE_NAME CURLOPT_SOCKS5_GSSAPI_SERVICE CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 + CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 CURLOPT_SSH_KNOWNHOSTS CURLOPT_SSH_PRIVATE_KEYFILE CURLOPT_SSH_PUBLIC_KEYFILE @@ -145,11 +148,13 @@ options: CURLOPT_USERNAME CURLOPT_USERPWD CURLOPT_XOAUTH2_BEARER - Else it is the same as for curl_easy_setopt(). + All blob options are also supported. + In all other cases, it ignores the ccsid parameter and behaves as +curl_easy_setopt(). Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the address of an (empty) character buffer, not the address of a string. -CURLOPT_POSTFIELDS stores the address of static binary data (of type void *) and -thus is not converted. If CURLOPT_COPYPOSTFIELDS is issued after +CURLOPT_POSTFIELDS stores the address of static binary data (of type void *) +and thus is not converted. If CURLOPT_COPYPOSTFIELDS is issued after CURLOPT_POSTFIELDSIZE != -1, the data size is adjusted according to the CCSID conversion result length. @@ -195,6 +200,13 @@ CCSID. Returned structures should be freed with curl_certinfo_free_all() after use. Other options are processed like in curl_easy_getinfo(). +_ curl_easy_strerror_ccsid(), curl_multi_strerror_ccsid(), +curl_share_strerror_ccsid() and curl_url_strerror_ccsid() work as their +non-ccsid version and return a string encoded in the additional ccsid +parameter. These strings belong to libcurl and may not be freed by the caller. +A subsequent call to the same procedure in the same thread invalidates the +previous result. + _ curl_pushheader_bynum_cssid() and curl_pushheader_byname_ccsid() Although the prototypes are self-explanatory, the returned string pointer should be released with curl_free() after use, as opposite to the non-ccsid @@ -208,6 +220,17 @@ ASCII, the curl_easy_option_get_name_ccsid() function allows getting it in any supported ccsid. However the caller should release the returned pointer with curl_free() after use. +_ curl_easy_header_ccsid() works as its non-CCSID counterpart but requires an +additional ccsid parameter specifying the name parameter encoding. The output +hout parameter is kept in libcurl's encoding and should not be altered. + +_ curl_from_ccsid() and curl_to_ccsid() are string encoding conversion +functions between ASCII (latin1) and the given CCSID. The first parameter is +the source string, the second is the CCSID and the returned value is a pointer +to the dynamically allocated string. These functions do not impact on Curl's +behavior and are only provided for user convenience. After use, returned values +must be released with curl_free(). + Standard compilation environment does support neither autotools nor make; in fact, very few common utilities are available. As a consequence, the @@ -270,7 +293,8 @@ _ Copy any file in the current directory to makelog (i.e.: cp initscript.sh makelog): this is intended to create the makelog file with an ASCII CCSID! _ Enter the command "sh makefile.sh > makelog 2>&1" -_ Examine the makelog file to check for compilation errors. +_ Examine the makelog file to check for compilation errors. CZM0383 warnings on + C or system standard API come from QADRT inlining and can safely be ignored. Leaving file initscript.sh unchanged, this will produce the following OS/400 objects: @@ -316,9 +340,9 @@ _ Do not use original source include files unless you know what you are doing. ILE/RPG support: - Since 95% of the OS/400 programmers use ILE/RPG exclusively, a definition - /INCLUDE member is provided for this language. To include all libcurl - definitions in an ILE/RPG module, line + Since most of the ILE OS/400 programmers use ILE/RPG exclusively, a +definition /INCLUDE member is provided for this language. To include all +libcurl definitions in an ILE/RPG module, line h bnddir('CURL/CURL') diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c index 86b6760c4..95dc65aad 100644 --- a/packages/OS400/ccsidcurl.c +++ b/packages/OS400/ccsidcurl.c @@ -235,28 +235,50 @@ slist_convert(int dccsid, struct curl_slist *from, int sccsid) } -char *curl_version_ccsid(unsigned int ccsid) +static char * +keyed_string(localkey_t key, const char *ascii, unsigned int ccsid) { int i; - char *aversion; - char *eversion; + char *ebcdic; - aversion = curl_version(); + if(!ascii) + return (char *) NULL; - if(!aversion) - return aversion; + i = MAX_CONV_EXPANSION * (strlen(ascii) + 1); - i = strlen(aversion) + 1; - i *= MAX_CONV_EXPANSION; + ebcdic = Curl_thread_buffer(key, i); + if(!ebcdic) + return ebcdic; - eversion = Curl_thread_buffer(LK_CURL_VERSION, i); - if(!eversion) + if(convert(ebcdic, i, ccsid, ascii, -1, ASCII_CCSID) < 0) return (char *) NULL; - if(convert(eversion, i, ccsid, aversion, -1, ASCII_CCSID) < 0) - return (char *) NULL; + return ebcdic; +} + + +const char * +curl_to_ccsid(const char *s, unsigned int ccsid) +{ + if(s) + s = dynconvert(ccsid, s, -1, ASCII_CCSID); + return s; +} - return eversion; + +const char * +curl_from_ccsid(const char *s, unsigned int ccsid) +{ + if(s) + s = dynconvert(ASCII_CCSID, s, -1, ccsid); + return s; +} + + +char * +curl_version_ccsid(unsigned int ccsid) +{ + return keyed_string(LK_CURL_VERSION, curl_version(), ccsid); } @@ -414,18 +436,19 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid) offsetof(curl_version_info_data, capath), offsetof(curl_version_info_data, zstd_version), offsetof(curl_version_info_data, hyper_version), - offsetof(curl_version_info_data, gsasl_version) + offsetof(curl_version_info_data, gsasl_version), + offsetof(curl_version_info_data, feature_names) }; /* The assertion below is possible, because although the second operand is an enum member, the first is a #define. In that case, the OS/400 C compiler seems to compare string values after substitution. */ -#if CURLVERSION_NOW != CURLVERSION_TENTH +#if CURLVERSION_NOW != CURLVERSION_ELEVENTH #error curl_version_info_data structure has changed: upgrade this procedure. #endif - /* If caller has been compiled with a new version, error. */ + /* If caller has been compiled with a newer version, error. */ if(stamp > CURLVERSION_NOW) return (curl_version_info_data *) NULL; @@ -498,75 +521,28 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid) const char * curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid) { - int i; - const char *s; - char *buf; - - s = curl_easy_strerror(error); - - if(!s) - return s; - - i = MAX_CONV_EXPANSION * (strlen(s) + 1); - - buf = Curl_thread_buffer(LK_EASY_STRERROR, i); - if(!buf) - return (const char *) NULL; - - if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0) - return (const char *) NULL; - - return (const char *) buf; + return keyed_string(LK_EASY_STRERROR, curl_easy_strerror(error), ccsid); } const char * curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid) { - int i; - const char *s; - char *buf; - - s = curl_share_strerror(error); - - if(!s) - return s; - - i = MAX_CONV_EXPANSION * (strlen(s) + 1); - - buf = Curl_thread_buffer(LK_SHARE_STRERROR, i); - if(!buf) - return (const char *) NULL; - - if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0) - return (const char *) NULL; - - return (const char *) buf; + return keyed_string(LK_SHARE_STRERROR, curl_share_strerror(error), ccsid); } const char * curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid) { - int i; - const char *s; - char *buf; - - s = curl_multi_strerror(error); - - if(!s) - return s; - - i = MAX_CONV_EXPANSION * (strlen(s) + 1); - - buf = Curl_thread_buffer(LK_MULTI_STRERROR, i); - if(!buf) - return (const char *) NULL; + return keyed_string(LK_MULTI_STRERROR, curl_multi_strerror(error), ccsid); +} - if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0) - return (const char *) NULL; - return (const char *) buf; +const char * +curl_url_strerror_ccsid(CURLUcode error, unsigned int ccsid) +{ + return keyed_string(LK_URL_STRERROR, curl_url_strerror(error), ccsid); } @@ -1087,17 +1063,15 @@ curl_formget_ccsid(struct curl_httppost *form, void *arg, CURLcode -curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) +curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) { CURLcode result; va_list arg; - struct Curl_easy *data; char *s; - char *cp; + char *cp = NULL; unsigned int ccsid; curl_off_t pfsize; - data = (struct Curl_easy *) curl; va_start(arg, tag); switch(tag) { @@ -1137,6 +1111,7 @@ curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) case CURLOPT_PASSWORD: case CURLOPT_PINNEDPUBLICKEY: case CURLOPT_PRE_PROXY: + case CURLOPT_PROTOCOLS_STR: case CURLOPT_PROXY: case CURLOPT_PROXYPASSWORD: case CURLOPT_PROXYUSERNAME: @@ -1158,6 +1133,7 @@ curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) case CURLOPT_PROXY_TLSAUTH_USERNAME: case CURLOPT_RANDOM_FILE: case CURLOPT_RANGE: + case CURLOPT_REDIR_PROTOCOLS_STR: case CURLOPT_REFERER: case CURLOPT_REQUEST_TARGET: case CURLOPT_RTSP_SESSION_ID: @@ -1167,6 +1143,7 @@ curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) case CURLOPT_SERVICE_NAME: case CURLOPT_SOCKS5_GSSAPI_SERVICE: case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: + case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256: case CURLOPT_SSH_KNOWNHOSTS: case CURLOPT_SSH_PRIVATE_KEYFILE: case CURLOPT_SSH_PUBLIC_KEYFILE: @@ -1199,7 +1176,7 @@ curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) } } - result = curl_easy_setopt(curl, tag, s); + result = curl_easy_setopt(easy, tag, s); free(s); break; @@ -1210,10 +1187,10 @@ curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) s = va_arg(arg, char *); ccsid = va_arg(arg, unsigned int); - pfsize = data->set.postfieldsize; + pfsize = easy->set.postfieldsize; if(!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) { - result = curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, s); + result = curl_easy_setopt(easy, CURLOPT_COPYPOSTFIELDS, s); break; } @@ -1251,30 +1228,68 @@ curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid); if(pfsize < 0) { - free(cp); result = CURLE_OUT_OF_MEMORY; break; } - data->set.postfieldsize = pfsize; /* Replace data size. */ + easy->set.postfieldsize = pfsize; /* Replace data size. */ s = cp; } - result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s); - data->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */ + result = curl_easy_setopt(easy, CURLOPT_POSTFIELDS, s); + easy->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */ break; - case CURLOPT_ERRORBUFFER: /* This is an output buffer. */ default: - result = Curl_vsetopt(curl, tag, arg); + if(tag / 10000 == CURLOPTTYPE_BLOB) { + struct curl_blob *bp = va_arg(arg, struct curl_blob *); + struct curl_blob blob; + + ccsid = va_arg(arg, unsigned int); + + if(bp && bp->data && bp->len && + ccsid != NOCONV_CCSID && ccsid != ASCII_CCSID) { + pfsize = (curl_off_t) bp->len * MAX_CONV_EXPANSION; + + if(pfsize > SIZE_MAX) + pfsize = SIZE_MAX; + + cp = malloc(pfsize); + + if(!cp) { + result = CURLE_OUT_OF_MEMORY; + break; + } + + pfsize = convert(cp, pfsize, ASCII_CCSID, bp->data, bp->len, ccsid); + + if(pfsize < 0) { + result = CURLE_OUT_OF_MEMORY; + break; + } + + blob.data = cp; + blob.len = pfsize; + blob.flags = bp->flags | CURL_BLOB_COPY; + bp = &blob; + } + result = curl_easy_setopt(easy, tag, &blob); + break; + } + /* FALLTHROUGH */ + case CURLOPT_ERRORBUFFER: /* This is an output buffer. */ + result = Curl_vsetopt(easy, tag, arg); break; } va_end(arg); + free(cp); return result; } +/* ILE/RPG helper functions. */ + char * curl_form_long_value(long value) { @@ -1460,3 +1475,24 @@ curl_easy_option_get_name_ccsid(const struct curl_easyoption *option, return (const char *) name; } + +/* Header API CCSID support. */ +CURLHcode +curl_easy_header_ccsid(CURL *easy, const char *name, size_t index, + unsigned int origin, int request, + struct curl_header **hout, unsigned int ccsid) +{ + CURLHcode result = CURLHE_BAD_ARGUMENT; + + if(name) { + char *s = dynconvert(ASCII_CCSID, name, -1, ccsid); + + result = CURLHE_OUT_OF_MEMORY; + if(s) { + result = curl_easy_header(easy, s, index, origin, request, hout); + free(s); + } + } + + return result; +} diff --git a/packages/OS400/ccsidcurl.h b/packages/OS400/ccsidcurl.h index a6d597b55..c51f81812 100644 --- a/packages/OS400/ccsidcurl.h +++ b/packages/OS400/ccsidcurl.h @@ -96,5 +96,14 @@ CURL_EXTERN const struct curl_easyoption *curl_easy_option_by_name_ccsid( CURL_EXTERN const char *curl_easy_option_get_name_ccsid( const struct curl_easyoption *option, unsigned int ccsid); +CURL_EXTERN const char *curl_url_strerror_ccsid(CURLUcode error, + unsigned int ccsid); +CURL_EXTERN CURLHcode curl_easy_header_ccsid(CURL *easy, const char *name, + size_t index, unsigned int origin, + int request, + struct curl_header **hout, + unsigned int ccsid); +CURL_EXTERN const char *curl_from_ccsid(const char *s, unsigned int ccsid); +CURL_EXTERN const char *curl_to_ccsid(const char *s, unsigned int ccsid); #endif diff --git a/packages/OS400/os400sys.h b/packages/OS400/os400sys.h index f3f461899..d5ff412f2 100644 --- a/packages/OS400/os400sys.h +++ b/packages/OS400/os400sys.h @@ -32,7 +32,6 @@ /* Per-thread item identifiers. */ typedef enum { - LK_SSL_ERROR, LK_GSK_ERROR, LK_LDAP_ERROR, LK_CURL_VERSION, @@ -41,6 +40,7 @@ typedef enum { LK_EASY_STRERROR, LK_SHARE_STRERROR, LK_MULTI_STRERROR, + LK_URL_STRERROR, LK_ZLIB_VERSION, LK_ZLIB_MSG, LK_LAST |