Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/curl/packages/OS400/ccsidcurl.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/curl/packages/OS400/ccsidcurl.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,1488 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * + ***************************************************************************/ + +/* CCSID API wrappers for OS/400. */ + +#include <iconv.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <stdarg.h> + +#pragma enum(int) + +#include "curl.h" +#include "mprintf.h" +#include "slist.h" +#include "urldata.h" +#include "url.h" +#include "setopt.h" +#include "getinfo.h" +#include "ccsidcurl.h" + +#include "os400sys.h" + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) ~0) /* Is unsigned on OS/400. */ +#endif + + +#define ASCII_CCSID 819 /* Use ISO-8859-1 as ASCII. */ +#define NOCONV_CCSID 65535 /* No conversion. */ +#define ICONV_ID_SIZE 32 /* Size of iconv_open() code identifier. */ +#define ICONV_OPEN_ERROR(t) ((t).return_value == -1) + +#define ALLOC_GRANULE 8 /* Alloc. granule for curl_formadd_ccsid(). */ + + +static void +makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid) + +{ + /** + *** Convert a CCSID to the corresponding IBM iconv_open() character + *** code identifier. + *** This code is specific to the OS400 implementation of the iconv library. + *** CCSID 65535 (no conversion) is replaced by the ASCII CCSID. + *** CCSID 0 is interpreted by the OS400 as the job's CCSID. + **/ + + ccsid &= 0xFFFF; + + if(ccsid == NOCONV_CCSID) + ccsid = ASCII_CCSID; + + memset(buf, 0, ICONV_ID_SIZE); + curl_msprintf(buf, "IBMCCSID%05u0000000", ccsid); +} + + +static iconv_t +iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin, + unsigned int cstr) + +{ + char fromcode[ICONV_ID_SIZE]; + char tocode[ICONV_ID_SIZE]; + + /** + *** Like iconv_open(), but character codes are given as CCSIDs. + *** If `cstr' is non-zero, conversion is set up to stop whenever a + *** null character is encountered. + *** See iconv_open() IBM description in "National Language Support API". + **/ + + makeOS400IconvCode(fromcode, ccsidin); + makeOS400IconvCode(tocode, ccsidout); + memset(tocode + 13, 0, sizeof(tocode) - 13); /* Dest. code id format. */ + + if(cstr) + fromcode[18] = '1'; /* Set null-terminator flag. */ + + return iconv_open(tocode, fromcode); +} + + +static int +convert(char *d, size_t dlen, int dccsid, + const char *s, int slen, int sccsid) + +{ + int i; + iconv_t cd; + size_t lslen; + + /** + *** Convert `sccsid'-coded `slen'-data bytes at `s' into `dccsid'-coded + *** data stored in the `dlen'-byte buffer at `d'. + *** If `slen' < 0, source string is null-terminated. + *** CCSID 65535 (no conversion) is replaced by the ASCII CCSID. + *** Return the converted destination byte count, or -1 if error. + **/ + + if(sccsid == 65535) + sccsid = ASCII_CCSID; + + if(dccsid == 65535) + dccsid = ASCII_CCSID; + + if(sccsid == dccsid) { + lslen = slen >= 0? slen: strlen(s) + 1; + i = lslen < dlen? lslen: dlen; + + if(s != d && i > 0) + memcpy(d, s, i); + + return i; + } + + if(slen < 0) { + lslen = 0; + cd = iconv_open_CCSID(dccsid, sccsid, 1); + } + else { + lslen = (size_t) slen; + cd = iconv_open_CCSID(dccsid, sccsid, 0); + } + + if(ICONV_OPEN_ERROR(cd)) + return -1; + + i = dlen; + + if((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0) + i = -1; + else + i -= dlen; + + iconv_close(cd); + return i; +} + + +static char * +dynconvert(int dccsid, const char *s, int slen, int sccsid) + +{ + char *d; + char *cp; + size_t dlen; + int l; + static const char nullbyte = 0; + + /* Like convert, but the destination is allocated and returned. */ + + dlen = (size_t) (slen < 0? strlen(s): slen) + 1; + dlen *= MAX_CONV_EXPANSION; /* Allow some expansion. */ + d = malloc(dlen); + + if(!d) + return (char *) NULL; + + l = convert(d, dlen, dccsid, s, slen, sccsid); + + if(l < 0) { + free(d); + return (char *) NULL; + } + + if(slen < 0) { + /* Need to null-terminate even when source length is given. + Since destination code size is unknown, use a conversion to generate + terminator. */ + + int l2 = convert(d + l, dlen - l, dccsid, &nullbyte, -1, ASCII_CCSID); + + if(l2 < 0) { + free(d); + return (char *) NULL; + } + + l += l2; + } + + if((size_t) l < dlen) { + cp = realloc(d, l); /* Shorten to minimum needed. */ + + if(cp) + d = cp; + } + + return d; +} + + +static struct curl_slist * +slist_convert(int dccsid, struct curl_slist *from, int sccsid) + +{ + struct curl_slist *to = (struct curl_slist *) NULL; + + for(; from; from = from->next) { + struct curl_slist *nl; + char *cp = dynconvert(dccsid, from->data, -1, sccsid); + + if(!cp) { + curl_slist_free_all(to); + return (struct curl_slist *) NULL; + } + nl = Curl_slist_append_nodup(to, cp); + if(!nl) { + curl_slist_free_all(to); + free(cp); + return NULL; + } + to = nl; + } + return to; +} + + +char * +curl_version_ccsid(unsigned int ccsid) + +{ + int i; + char *aversion; + char *eversion; + + aversion = curl_version(); + + if(!aversion) + return aversion; + + i = strlen(aversion) + 1; + i *= MAX_CONV_EXPANSION; + + eversion = Curl_thread_buffer(LK_CURL_VERSION, i); + if(!eversion) + return (char *) NULL; + + if(convert(eversion, i, ccsid, aversion, -1, ASCII_CCSID) < 0) + return (char *) NULL; + + return eversion; +} + + +char * +curl_easy_escape_ccsid(CURL *handle, const char *string, int length, + unsigned int sccsid, unsigned int dccsid) + +{ + char *s; + char *d; + + if(!string) { + errno = EINVAL; + return (char *) NULL; + } + + s = dynconvert(ASCII_CCSID, string, length? length: -1, sccsid); + + if(!s) + return (char *) NULL; + + d = curl_easy_escape(handle, s, 0); + free(s); + + if(!d) + return (char *) NULL; + + s = dynconvert(dccsid, d, -1, ASCII_CCSID); + free(d); + return s; +} + + +char * +curl_easy_unescape_ccsid(CURL *handle, const char *string, int length, + int *outlength, + unsigned int sccsid, unsigned int dccsid) + +{ + char *s; + char *d; + + if(!string) { + errno = EINVAL; + return (char *) NULL; + } + + s = dynconvert(ASCII_CCSID, string, length? length: -1, sccsid); + + if(!s) + return (char *) NULL; + + d = curl_easy_unescape(handle, s, 0, outlength); + free(s); + + if(!d) + return (char *) NULL; + + s = dynconvert(dccsid, d, -1, ASCII_CCSID); + free(d); + + if(s && outlength) + *outlength = strlen(s); + + return s; +} + + +struct curl_slist * +curl_slist_append_ccsid(struct curl_slist *list, + const char *data, unsigned int ccsid) + +{ + char *s; + + s = (char *) NULL; + + if(!data) + return curl_slist_append(list, data); + + s = dynconvert(ASCII_CCSID, data, -1, ccsid); + + if(!s) + return (struct curl_slist *) NULL; + + list = curl_slist_append(list, s); + free(s); + return list; +} + + +time_t +curl_getdate_ccsid(const char *p, const time_t * unused, unsigned int ccsid) + +{ + char *s; + time_t t; + + if(!p) + return curl_getdate(p, unused); + + s = dynconvert(ASCII_CCSID, p, -1, ccsid); + + if(!s) + return (time_t) -1; + + t = curl_getdate(s, unused); + free(s); + return t; +} + + +static int +convert_version_info_string(const char * * stringp, + char * * bufp, int *left, unsigned int ccsid) + +{ + /* Helper for curl_version_info_ccsid(): convert a string if defined. + Result is stored in the `*left'-byte buffer at `*bufp'. + `*bufp' and `*left' are updated accordingly. + Return 0 if ok, else -1. */ + + if(*stringp) { + int l = convert(*bufp, *left, ccsid, *stringp, -1, ASCII_CCSID); + + if(l <= 0) + return -1; + + *stringp = *bufp; + *bufp += l; + *left -= l; + } + + return 0; +} + + +curl_version_info_data * +curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid) + +{ + curl_version_info_data * p; + char *cp; + int n; + int nproto; + curl_version_info_data * id; + + /* 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_FOURTH +#error curl_version_info_data structure has changed: upgrade this procedure. +#endif + + /* If caller has been compiled with a new version, error. */ + + if(stamp > CURLVERSION_NOW) + return (curl_version_info_data *) NULL; + + p = curl_version_info(stamp); + + if(!p) + return p; + + /* Measure thread space needed. */ + + n = 0; + nproto = 0; + + if(p->protocols) { + while(p->protocols[nproto]) + n += strlen(p->protocols[nproto++]); + + n += nproto++; + } + + if(p->version) + n += strlen(p->version) + 1; + + if(p->host) + n += strlen(p->host) + 1; + + if(p->ssl_version) + n += strlen(p->ssl_version) + 1; + + if(p->libz_version) + n += strlen(p->libz_version) + 1; + + if(p->ares) + n += strlen(p->ares) + 1; + + if(p->libidn) + n += strlen(p->libidn) + 1; + + if(p->libssh_version) + n += strlen(p->libssh_version) + 1; + + /* Allocate thread space. */ + + n *= MAX_CONV_EXPANSION; + + if(nproto) + n += nproto * sizeof(const char *); + + cp = Curl_thread_buffer(LK_VERSION_INFO_DATA, n); + id = (curl_version_info_data *) Curl_thread_buffer(LK_VERSION_INFO, + sizeof(*id)); + + if(!id || !cp) + return (curl_version_info_data *) NULL; + + /* Copy data and convert strings. */ + + memcpy((char *) id, (char *) p, sizeof(*p)); + + if(id->protocols) { + int i = nproto * sizeof(id->protocols[0]); + + id->protocols = (const char * const *) cp; + memcpy(cp, (char *) p->protocols, i); + cp += i; + n -= i; + + for(i = 0; id->protocols[i]; i++) + if(convert_version_info_string(((const char * *) id->protocols) + i, + &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + } + + if(convert_version_info_string(&id->version, &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + + if(convert_version_info_string(&id->host, &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + + if(convert_version_info_string(&id->ssl_version, &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + + if(convert_version_info_string(&id->libz_version, &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + + if(convert_version_info_string(&id->ares, &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + + if(convert_version_info_string(&id->libidn, &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + + if(convert_version_info_string(&id->libssh_version, &cp, &n, ccsid)) + return (curl_version_info_data *) NULL; + + return id; +} + + +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; +} + + +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; +} + + +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; + + if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0) + return (const char *) NULL; + + return (const char *) buf; +} + + +void +curl_certinfo_free_all(struct curl_certinfo *info) + +{ + /* Free all memory used by certificate info. */ + if(info) { + if(info->certinfo) { + int i; + + for(i = 0; i < info->num_of_certs; i++) + curl_slist_free_all(info->certinfo[i]); + free((char *) info->certinfo); + } + free((char *) info); + } +} + + +CURLcode +curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) + +{ + va_list arg; + void *paramp; + CURLcode ret; + struct Curl_easy * data; + + /* WARNING: unlike curl_easy_getinfo(), the strings returned by this + procedure have to be free'ed. */ + + data = (struct Curl_easy *) curl; + va_start(arg, info); + paramp = va_arg(arg, void *); + ret = Curl_getinfo(data, info, paramp); + + if(ret == CURLE_OK) { + unsigned int ccsid; + char **cpp; + struct curl_slist **slp; + struct curl_certinfo *cipf; + struct curl_certinfo *cipt; + + switch((int) info & CURLINFO_TYPEMASK) { + + case CURLINFO_STRING: + ccsid = va_arg(arg, unsigned int); + cpp = (char * *) paramp; + + if(*cpp) { + *cpp = dynconvert(ccsid, *cpp, -1, ASCII_CCSID); + + if(!*cpp) + ret = CURLE_OUT_OF_MEMORY; + } + + break; + + case CURLINFO_SLIST: + ccsid = va_arg(arg, unsigned int); + switch(info) { + case CURLINFO_CERTINFO: + cipf = *(struct curl_certinfo * *) paramp; + if(cipf) { + cipt = (struct curl_certinfo *) malloc(sizeof(*cipt)); + if(!cipt) + ret = CURLE_OUT_OF_MEMORY; + else { + cipt->certinfo = (struct curl_slist **) + calloc(cipf->num_of_certs + + 1, sizeof(struct curl_slist *)); + if(!cipt->certinfo) + ret = CURLE_OUT_OF_MEMORY; + else { + int i; + + cipt->num_of_certs = cipf->num_of_certs; + for(i = 0; i < cipf->num_of_certs; i++) + if(cipf->certinfo[i]) + if(!(cipt->certinfo[i] = slist_convert(ccsid, + cipf->certinfo[i], + ASCII_CCSID))) { + ret = CURLE_OUT_OF_MEMORY; + break; + } + } + } + + if(ret != CURLE_OK) { + curl_certinfo_free_all(cipt); + cipt = (struct curl_certinfo *) NULL; + } + + *(struct curl_certinfo * *) paramp = cipt; + } + + break; + + case CURLINFO_TLS_SESSION: + case CURLINFO_TLS_SSL_PTR: + case CURLINFO_SOCKET: + break; + + default: + slp = (struct curl_slist **) paramp; + if(*slp) { + *slp = slist_convert(ccsid, *slp, ASCII_CCSID); + if(!*slp) + ret = CURLE_OUT_OF_MEMORY; + } + break; + } + } + } + + va_end(arg); + return ret; +} + + +static int +Curl_is_formadd_string(CURLformoption option) + +{ + switch(option) { + + case CURLFORM_FILENAME: + case CURLFORM_CONTENTTYPE: + case CURLFORM_BUFFER: + case CURLFORM_FILE: + case CURLFORM_FILECONTENT: + case CURLFORM_COPYCONTENTS: + case CURLFORM_COPYNAME: + return 1; + } + + return 0; +} + + +static void +Curl_formadd_release_local(struct curl_forms * forms, int nargs, int skip) + +{ + while(nargs--) + if(nargs != skip) + if(Curl_is_formadd_string(forms[nargs].option)) + if(forms[nargs].value) + free((char *) forms[nargs].value); + + free((char *) forms); +} + + +static int +Curl_formadd_convert(struct curl_forms * forms, + int formx, int lengthx, unsigned int ccsid) + +{ + int l; + char *cp; + char *cp2; + + if(formx < 0 || !forms[formx].value) + return 0; + + if(lengthx >= 0) + l = (int) forms[lengthx].value; + else + l = strlen(forms[formx].value) + 1; + + cp = malloc(MAX_CONV_EXPANSION * l); + + if(!cp) + return -1; + + l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID, + forms[formx].value, l, ccsid); + + if(l < 0) { + free(cp); + return -1; + } + + cp2 = realloc(cp, l); /* Shorten buffer to the string size. */ + + if(cp2) + cp = cp2; + + forms[formx].value = cp; + + if(lengthx >= 0) + forms[lengthx].value = (char *) l; /* Update length after conversion. */ + + return l; +} + + +CURLFORMcode +curl_formadd_ccsid(struct curl_httppost * * httppost, + struct curl_httppost * * last_post, ...) + +{ + va_list arg; + CURLformoption option; + CURLFORMcode result; + struct curl_forms * forms; + struct curl_forms * lforms; + struct curl_forms * tforms; + unsigned int lformlen; + const char *value; + unsigned int ccsid; + int nargs; + int namex; + int namelengthx; + int contentx; + int lengthx; + unsigned int contentccsid; + unsigned int nameccsid; + + /* A single curl_formadd() call cannot be split in several calls to deal + with all parameters: the original parameters are thus copied to a local + curl_forms array and converted to ASCII when needed. + CURLFORM_PTRNAME is processed as if it were CURLFORM_COPYNAME. + CURLFORM_COPYNAME and CURLFORM_NAMELENGTH occurrence order in + parameters is not defined; for this reason, the actual conversion is + delayed to the end of parameter processing. The same applies to + CURLFORM_COPYCONTENTS/CURLFORM_CONTENTSLENGTH, but these may appear + several times in the parameter list; the problem resides here in knowing + which CURLFORM_CONTENTSLENGTH applies to which CURLFORM_COPYCONTENTS and + when we can be sure to have both info for conversion: end of parameter + list is such a point, but CURLFORM_CONTENTTYPE is also used here as a + natural separator between content data definitions; this seems to be + in accordance with FormAdd() behavior. */ + + /* Allocate the local curl_forms array. */ + + lformlen = ALLOC_GRANULE; + lforms = malloc(lformlen * sizeof(*lforms)); + + if(!lforms) + return CURL_FORMADD_MEMORY; + + /* Process the arguments, copying them into local array, latching conversion + indexes and converting when needed. */ + + result = CURL_FORMADD_OK; + nargs = 0; + contentx = -1; + lengthx = -1; + namex = -1; + namelengthx = -1; + forms = (struct curl_forms *) NULL; + va_start(arg, last_post); + + for(;;) { + /* Make sure there is still room for an item in local array. */ + + if(nargs >= lformlen) { + lformlen += ALLOC_GRANULE; + tforms = realloc(lforms, lformlen * sizeof(*lforms)); + + if(!tforms) { + result = CURL_FORMADD_MEMORY; + break; + } + + lforms = tforms; + } + + /* Get next option. */ + + if(forms) { + /* Get option from array. */ + + option = forms->option; + value = forms->value; + forms++; + } + else { + /* Get option from arguments. */ + + option = va_arg(arg, CURLformoption); + + if(option == CURLFORM_END) + break; + } + + /* Dispatch by option. */ + + switch(option) { + + case CURLFORM_END: + forms = (struct curl_forms *) NULL; /* Leave array mode. */ + continue; + + case CURLFORM_ARRAY: + if(!forms) { + forms = va_arg(arg, struct curl_forms *); + continue; + } + + result = CURL_FORMADD_ILLEGAL_ARRAY; + break; + + case CURLFORM_COPYNAME: + option = CURLFORM_PTRNAME; /* Static for now. */ + + case CURLFORM_PTRNAME: + if(namex >= 0) + result = CURL_FORMADD_OPTION_TWICE; + + namex = nargs; + + if(!forms) { + value = va_arg(arg, char *); + nameccsid = (unsigned int) va_arg(arg, long); + } + else { + nameccsid = (unsigned int) forms->value; + forms++; + } + + break; + + case CURLFORM_COPYCONTENTS: + if(contentx >= 0) + result = CURL_FORMADD_OPTION_TWICE; + + contentx = nargs; + + if(!forms) { + value = va_arg(arg, char *); + contentccsid = (unsigned int) va_arg(arg, long); + } + else { + contentccsid = (unsigned int) forms->value; + forms++; + } + + break; + + case CURLFORM_PTRCONTENTS: + case CURLFORM_BUFFERPTR: + if(!forms) + value = va_arg(arg, char *); /* No conversion. */ + + break; + + case CURLFORM_CONTENTSLENGTH: + lengthx = nargs; + + if(!forms) + value = (char *) va_arg(arg, long); + + break; + + case CURLFORM_CONTENTLEN: + lengthx = nargs; + + if(!forms) + value = (char *) va_arg(arg, curl_off_t); + + break; + + case CURLFORM_NAMELENGTH: + namelengthx = nargs; + + if(!forms) + value = (char *) va_arg(arg, long); + + break; + + case CURLFORM_BUFFERLENGTH: + if(!forms) + value = (char *) va_arg(arg, long); + + break; + + case CURLFORM_CONTENTHEADER: + if(!forms) + value = (char *) va_arg(arg, struct curl_slist *); + + break; + + case CURLFORM_STREAM: + if(!forms) + value = (char *) va_arg(arg, void *); + + break; + + case CURLFORM_CONTENTTYPE: + /* If a previous content has been encountered, convert it now. */ + + if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) { + result = CURL_FORMADD_MEMORY; + break; + } + + contentx = -1; + lengthx = -1; + /* Fall into default. */ + + default: + /* Must be a convertible string. */ + + if(!Curl_is_formadd_string(option)) { + result = CURL_FORMADD_UNKNOWN_OPTION; + break; + } + + if(!forms) { + value = va_arg(arg, char *); + ccsid = (unsigned int) va_arg(arg, long); + } + else { + ccsid = (unsigned int) forms->value; + forms++; + } + + /* Do the conversion. */ + + lforms[nargs].value = value; + + if(Curl_formadd_convert(lforms, nargs, -1, ccsid) < 0) { + result = CURL_FORMADD_MEMORY; + break; + } + + value = lforms[nargs].value; + } + + if(result != CURL_FORMADD_OK) + break; + + lforms[nargs].value = value; + lforms[nargs++].option = option; + } + + va_end(arg); + + /* Convert the name and the last content, now that we know their lengths. */ + + if(result == CURL_FORMADD_OK && namex >= 0) { + if(Curl_formadd_convert(lforms, namex, namelengthx, nameccsid) < 0) + result = CURL_FORMADD_MEMORY; + else + lforms[namex].option = CURLFORM_COPYNAME; /* Force copy. */ + } + + if(result == CURL_FORMADD_OK) { + if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) + result = CURL_FORMADD_MEMORY; + else + contentx = -1; + } + + /* Do the formadd with our converted parameters. */ + + if(result == CURL_FORMADD_OK) { + lforms[nargs].option = CURLFORM_END; + result = curl_formadd(httppost, last_post, + CURLFORM_ARRAY, lforms, CURLFORM_END); + } + + /* Terminate. */ + + Curl_formadd_release_local(lforms, nargs, contentx); + return result; +} + + +typedef struct { + curl_formget_callback append; + void * arg; + unsigned int ccsid; +} cfcdata; + + +static size_t +Curl_formget_callback_ccsid(void *arg, const char *buf, size_t len) + +{ + cfcdata * p; + char *b; + int l; + size_t ret; + + p = (cfcdata *) arg; + + if((long) len <= 0) + return (*p->append)(p->arg, buf, len); + + b = malloc(MAX_CONV_EXPANSION * len); + + if(!b) + return (size_t) -1; + + l = convert(b, MAX_CONV_EXPANSION * len, p->ccsid, buf, len, ASCII_CCSID); + + if(l < 0) { + free(b); + return (size_t) -1; + } + + ret = (*p->append)(p->arg, b, l); + free(b); + return ret == l? len: -1; +} + + +int +curl_formget_ccsid(struct curl_httppost *form, void *arg, + curl_formget_callback append, unsigned int ccsid) + +{ + cfcdata lcfc; + + lcfc.append = append; + lcfc.arg = arg; + lcfc.ccsid = ccsid; + return curl_formget(form, (void *) &lcfc, Curl_formget_callback_ccsid); +} + + +CURLcode +curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...) + +{ + CURLcode result; + va_list arg; + struct Curl_easy *data; + char *s; + char *cp; + unsigned int ccsid; + curl_off_t pfsize; + static char testwarn = 1; + + /* Warns if this procedure has not been updated when the dupstring enum + changes. + We (try to) do it only once: there is no need to issue several times + the same message; but since threadsafeness is not handled here, + this may occur (and we don't care!). */ + + if(testwarn) { + testwarn = 0; + + if((int) STRING_LASTZEROTERMINATED != (int) STRING_SASL_AUTHZID + 1 || + (int) STRING_LAST != (int) STRING_COPYPOSTFIELDS + 1) + curl_mfprintf(stderr, + "*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n"); + } + + data = (struct Curl_easy *) curl; + va_start(arg, tag); + + switch(tag) { + + case CURLOPT_ABSTRACT_UNIX_SOCKET: + case CURLOPT_ALTSVC: + case CURLOPT_CAINFO: + case CURLOPT_CAPATH: + case CURLOPT_COOKIE: + case CURLOPT_COOKIEFILE: + case CURLOPT_COOKIEJAR: + case CURLOPT_COOKIELIST: + case CURLOPT_CRLFILE: + case CURLOPT_CUSTOMREQUEST: + case CURLOPT_DEFAULT_PROTOCOL: + case CURLOPT_DNS_SERVERS: + case CURLOPT_DOH_URL: + case CURLOPT_EGDSOCKET: + case CURLOPT_ENCODING: + case CURLOPT_FTPPORT: + case CURLOPT_FTP_ACCOUNT: + case CURLOPT_FTP_ALTERNATIVE_TO_USER: + case CURLOPT_INTERFACE: + case CURLOPT_ISSUERCERT: + case CURLOPT_KEYPASSWD: + case CURLOPT_KRBLEVEL: + case CURLOPT_LOGIN_OPTIONS: + case CURLOPT_MAIL_AUTH: + case CURLOPT_MAIL_FROM: + case CURLOPT_NETRC_FILE: + case CURLOPT_NOPROXY: + case CURLOPT_PASSWORD: + case CURLOPT_PINNEDPUBLICKEY: + case CURLOPT_PRE_PROXY: + case CURLOPT_PROXY: + case CURLOPT_PROXYPASSWORD: + case CURLOPT_PROXYUSERNAME: + case CURLOPT_PROXYUSERPWD: + case CURLOPT_PROXY_CAINFO: + case CURLOPT_PROXY_CAPATH: + case CURLOPT_PROXY_CRLFILE: + case CURLOPT_PROXY_KEYPASSWD: + case CURLOPT_PROXY_PINNEDPUBLICKEY: + case CURLOPT_PROXY_SERVICE_NAME: + case CURLOPT_PROXY_SSLCERT: + case CURLOPT_PROXY_SSLCERTTYPE: + case CURLOPT_PROXY_SSLKEY: + case CURLOPT_PROXY_SSLKEYTYPE: + case CURLOPT_PROXY_SSL_CIPHER_LIST: + case CURLOPT_PROXY_TLS13_CIPHERS: + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + case CURLOPT_PROXY_TLSAUTH_TYPE: + case CURLOPT_PROXY_TLSAUTH_USERNAME: + case CURLOPT_RANDOM_FILE: + case CURLOPT_RANGE: + case CURLOPT_REFERER: + case CURLOPT_REQUEST_TARGET: + case CURLOPT_RTSP_SESSION_ID: + case CURLOPT_RTSP_STREAM_URI: + case CURLOPT_RTSP_TRANSPORT: + case CURLOPT_SASL_AUTHZID: + case CURLOPT_SERVICE_NAME: + case CURLOPT_SOCKS5_GSSAPI_SERVICE: + case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: + case CURLOPT_SSH_KNOWNHOSTS: + case CURLOPT_SSH_PRIVATE_KEYFILE: + case CURLOPT_SSH_PUBLIC_KEYFILE: + case CURLOPT_SSLCERT: + case CURLOPT_SSLCERTTYPE: + case CURLOPT_SSLENGINE: + case CURLOPT_SSLKEY: + case CURLOPT_SSLKEYTYPE: + case CURLOPT_SSL_CIPHER_LIST: + case CURLOPT_TLS13_CIPHERS: + case CURLOPT_TLSAUTH_PASSWORD: + case CURLOPT_TLSAUTH_TYPE: + case CURLOPT_TLSAUTH_USERNAME: + case CURLOPT_UNIX_SOCKET_PATH: + case CURLOPT_URL: + case CURLOPT_USERAGENT: + case CURLOPT_USERNAME: + case CURLOPT_USERPWD: + case CURLOPT_XOAUTH2_BEARER: + s = va_arg(arg, char *); + ccsid = va_arg(arg, unsigned int); + + if(s) { + s = dynconvert(ASCII_CCSID, s, -1, ccsid); + + if(!s) { + result = CURLE_OUT_OF_MEMORY; + break; + } + } + + result = curl_easy_setopt(curl, tag, s); + free(s); + break; + + case CURLOPT_COPYPOSTFIELDS: + /* Special case: byte count may have been given by CURLOPT_POSTFIELDSIZE + prior to this call. In this case, convert the given byte count and + replace the length according to the conversion result. */ + s = va_arg(arg, char *); + ccsid = va_arg(arg, unsigned int); + + pfsize = data->set.postfieldsize; + + if(!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) { + result = curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, s); + break; + } + + if(pfsize == -1) { + /* Data is null-terminated. */ + s = dynconvert(ASCII_CCSID, s, -1, ccsid); + + if(!s) { + result = CURLE_OUT_OF_MEMORY; + break; + } + } + else { + /* Data length specified. */ + size_t len; + + if(pfsize < 0 || pfsize > SIZE_MAX) { + result = CURLE_OUT_OF_MEMORY; + break; + } + + len = pfsize; + pfsize = 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, s, len, ccsid); + + if(pfsize < 0) { + free(cp); + result = CURLE_OUT_OF_MEMORY; + break; + } + + data->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. */ + break; + + case CURLOPT_ERRORBUFFER: /* This is an output buffer. */ + default: + result = Curl_vsetopt(curl, tag, arg); + break; + } + + va_end(arg); + return result; +} + + +char * +curl_form_long_value(long value) + +{ + /* ILE/RPG cannot cast an integer to a pointer. This procedure does it. */ + + return (char *) value; +} + + +char * +curl_pushheader_bynum_cssid(struct curl_pushheaders *h, + size_t num, unsigned int ccsid) + +{ + char *d = (char *) NULL; + char *s = curl_pushheader_bynum(h, num); + + if(s) + d = dynconvert(ccsid, s, -1, ASCII_CCSID); + + return d; +} + + +char * +curl_pushheader_byname_ccsid(struct curl_pushheaders *h, const char *header, + unsigned int ccsidin, unsigned int ccsidout) + +{ + char *d = (char *) NULL; + + if(header) { + header = dynconvert(ASCII_CCSID, header, -1, ccsidin); + + if(header) { + char *s = curl_pushheader_byname(h, header); + free((char *) header); + + if(s) + d = dynconvert(ccsidout, s, -1, ASCII_CCSID); + } + } + + return d; +} + +static CURLcode +mime_string_call(curl_mimepart *part, const char *string, unsigned int ccsid, + CURLcode (*mimefunc)(curl_mimepart *part, const char *string)) + +{ + char *s = (char *) NULL; + CURLcode result; + + if(!string) + return mimefunc(part, string); + s = dynconvert(ASCII_CCSID, string, -1, ccsid); + if(!s) + return CURLE_OUT_OF_MEMORY; + + result = mimefunc(part, s); + free(s); + return result; +} + +CURLcode +curl_mime_name_ccsid(curl_mimepart *part, const char *name, unsigned int ccsid) + +{ + return mime_string_call(part, name, ccsid, curl_mime_name); +} + +CURLcode +curl_mime_filename_ccsid(curl_mimepart *part, + const char *filename, unsigned int ccsid) + +{ + return mime_string_call(part, filename, ccsid, curl_mime_filename); +} + +CURLcode +curl_mime_type_ccsid(curl_mimepart *part, + const char *mimetype, unsigned int ccsid) + +{ + return mime_string_call(part, mimetype, ccsid, curl_mime_type); +} + +CURLcode +curl_mime_encoder_ccsid(curl_mimepart *part, + const char *encoding, unsigned int ccsid) + +{ + return mime_string_call(part, encoding, ccsid, curl_mime_encoder); +} + +CURLcode +curl_mime_filedata_ccsid(curl_mimepart *part, + const char *filename, unsigned int ccsid) + +{ + return mime_string_call(part, filename, ccsid, curl_mime_filedata); +} + +CURLcode +curl_mime_data_ccsid(curl_mimepart *part, + const char *data, size_t datasize, unsigned int ccsid) + +{ + char *s = (char *) NULL; + CURLcode result; + + if(!data) + return curl_mime_data(part, data, datasize); + s = dynconvert(ASCII_CCSID, data, datasize, ccsid); + if(!s) + return CURLE_OUT_OF_MEMORY; + + result = curl_mime_data(part, s, datasize); + free(s); + return result; +} + +CURLUcode +curl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part, + unsigned int flags, unsigned int ccsid) + +{ + char *s = (char *)NULL; + CURLUcode result; + + if(!part) + return CURLUE_BAD_PARTPOINTER; + + *part = (char *)NULL; + result = curl_url_get(handle, what, &s, flags); + if(result == CURLUE_OK) { + if(s) { + *part = dynconvert(ccsid, s, -1, ASCII_CCSID); + if(!*part) + result = CURLUE_OUT_OF_MEMORY; + } + } + if(s) + free(s); + return result; +} + +CURLUcode +curl_url_set_ccsid(CURLU *handle, CURLUPart what, const char *part, + unsigned int flags, unsigned int ccsid) + +{ + char *s = (char *)NULL; + CURLUcode result; + + if(part) { + s = dynconvert(ASCII_CCSID, part, -1, ccsid); + if(!s) + return CURLUE_OUT_OF_MEMORY; + } + result = curl_url_set(handle, what, s, flags); + if(s) + free(s); + return result; +}
