113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci *
2413498266Sopenharmony_ci ***************************************************************************/
2513498266Sopenharmony_ci
2613498266Sopenharmony_ci/* CCSID API wrappers for OS/400. */
2713498266Sopenharmony_ci
2813498266Sopenharmony_ci#include <iconv.h>
2913498266Sopenharmony_ci#include <string.h>
3013498266Sopenharmony_ci#include <stdlib.h>
3113498266Sopenharmony_ci#include <stddef.h>
3213498266Sopenharmony_ci#include <errno.h>
3313498266Sopenharmony_ci#include <stdarg.h>
3413498266Sopenharmony_ci
3513498266Sopenharmony_ci#pragma enum(int)
3613498266Sopenharmony_ci
3713498266Sopenharmony_ci#include "curl.h"
3813498266Sopenharmony_ci#include "mprintf.h"
3913498266Sopenharmony_ci#include "slist.h"
4013498266Sopenharmony_ci#include "urldata.h"
4113498266Sopenharmony_ci#include "url.h"
4213498266Sopenharmony_ci#include "setopt.h"
4313498266Sopenharmony_ci#include "getinfo.h"
4413498266Sopenharmony_ci#include "ccsidcurl.h"
4513498266Sopenharmony_ci
4613498266Sopenharmony_ci#include "os400sys.h"
4713498266Sopenharmony_ci
4813498266Sopenharmony_ci#ifndef SIZE_MAX
4913498266Sopenharmony_ci#define SIZE_MAX        ((size_t) ~0)   /* Is unsigned on OS/400. */
5013498266Sopenharmony_ci#endif
5113498266Sopenharmony_ci
5213498266Sopenharmony_ci
5313498266Sopenharmony_ci#define ASCII_CCSID     819     /* Use ISO-8859-1 as ASCII. */
5413498266Sopenharmony_ci#define NOCONV_CCSID    65535   /* No conversion. */
5513498266Sopenharmony_ci#define ICONV_ID_SIZE   32      /* Size of iconv_open() code identifier. */
5613498266Sopenharmony_ci#define ICONV_OPEN_ERROR(t)     ((t).return_value == -1)
5713498266Sopenharmony_ci
5813498266Sopenharmony_ci#define ALLOC_GRANULE   8       /* Alloc. granule for curl_formadd_ccsid(). */
5913498266Sopenharmony_ci
6013498266Sopenharmony_ci
6113498266Sopenharmony_cistatic void
6213498266Sopenharmony_cimakeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
6313498266Sopenharmony_ci{
6413498266Sopenharmony_ci  /**
6513498266Sopenharmony_ci  *** Convert a CCSID to the corresponding IBM iconv_open() character
6613498266Sopenharmony_ci  ***  code identifier.
6713498266Sopenharmony_ci  ***  This code is specific to the OS400 implementation of the iconv library.
6813498266Sopenharmony_ci  ***  CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
6913498266Sopenharmony_ci  ***  CCSID 0 is interpreted by the OS400 as the job's CCSID.
7013498266Sopenharmony_ci  **/
7113498266Sopenharmony_ci
7213498266Sopenharmony_ci  ccsid &= 0xFFFF;
7313498266Sopenharmony_ci
7413498266Sopenharmony_ci  if(ccsid == NOCONV_CCSID)
7513498266Sopenharmony_ci    ccsid = ASCII_CCSID;
7613498266Sopenharmony_ci
7713498266Sopenharmony_ci  memset(buf, 0, ICONV_ID_SIZE);
7813498266Sopenharmony_ci  curl_msprintf(buf, "IBMCCSID%05u0000000", ccsid);
7913498266Sopenharmony_ci}
8013498266Sopenharmony_ci
8113498266Sopenharmony_ci
8213498266Sopenharmony_cistatic iconv_t
8313498266Sopenharmony_ciiconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin,
8413498266Sopenharmony_ci                 unsigned int cstr)
8513498266Sopenharmony_ci{
8613498266Sopenharmony_ci  char fromcode[ICONV_ID_SIZE];
8713498266Sopenharmony_ci  char tocode[ICONV_ID_SIZE];
8813498266Sopenharmony_ci
8913498266Sopenharmony_ci  /**
9013498266Sopenharmony_ci  ***  Like iconv_open(), but character codes are given as CCSIDs.
9113498266Sopenharmony_ci  ***  If `cstr' is non-zero, conversion is set up to stop whenever a
9213498266Sopenharmony_ci  ***   null character is encountered.
9313498266Sopenharmony_ci  ***  See iconv_open() IBM description in "National Language Support API".
9413498266Sopenharmony_ci  **/
9513498266Sopenharmony_ci
9613498266Sopenharmony_ci  makeOS400IconvCode(fromcode, ccsidin);
9713498266Sopenharmony_ci  makeOS400IconvCode(tocode, ccsidout);
9813498266Sopenharmony_ci  memset(tocode + 13, 0, sizeof(tocode) - 13);   /* Dest. code id format. */
9913498266Sopenharmony_ci
10013498266Sopenharmony_ci  if(cstr)
10113498266Sopenharmony_ci    fromcode[18] = '1';                         /* Set null-terminator flag. */
10213498266Sopenharmony_ci
10313498266Sopenharmony_ci  return iconv_open(tocode, fromcode);
10413498266Sopenharmony_ci}
10513498266Sopenharmony_ci
10613498266Sopenharmony_ci
10713498266Sopenharmony_cistatic int
10813498266Sopenharmony_ciconvert(char *d, size_t dlen, int dccsid,
10913498266Sopenharmony_ci        const char *s, int slen, int sccsid)
11013498266Sopenharmony_ci{
11113498266Sopenharmony_ci  int i;
11213498266Sopenharmony_ci  iconv_t cd;
11313498266Sopenharmony_ci  size_t lslen;
11413498266Sopenharmony_ci
11513498266Sopenharmony_ci  /**
11613498266Sopenharmony_ci  ***  Convert `sccsid'-coded `slen'-data bytes at `s' into `dccsid'-coded
11713498266Sopenharmony_ci  ***   data stored in the `dlen'-byte buffer at `d'.
11813498266Sopenharmony_ci  ***  If `slen' < 0, source string is null-terminated.
11913498266Sopenharmony_ci  ***  CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
12013498266Sopenharmony_ci  ***  Return the converted destination byte count, or -1 if error.
12113498266Sopenharmony_ci  **/
12213498266Sopenharmony_ci
12313498266Sopenharmony_ci  if(sccsid == 65535)
12413498266Sopenharmony_ci    sccsid = ASCII_CCSID;
12513498266Sopenharmony_ci
12613498266Sopenharmony_ci  if(dccsid == 65535)
12713498266Sopenharmony_ci    dccsid = ASCII_CCSID;
12813498266Sopenharmony_ci
12913498266Sopenharmony_ci  if(sccsid == dccsid) {
13013498266Sopenharmony_ci    lslen = slen >= 0? slen: strlen(s) + 1;
13113498266Sopenharmony_ci    i = lslen < dlen? lslen: dlen;
13213498266Sopenharmony_ci
13313498266Sopenharmony_ci    if(s != d && i > 0)
13413498266Sopenharmony_ci      memcpy(d, s, i);
13513498266Sopenharmony_ci
13613498266Sopenharmony_ci    return i;
13713498266Sopenharmony_ci    }
13813498266Sopenharmony_ci
13913498266Sopenharmony_ci  if(slen < 0) {
14013498266Sopenharmony_ci    lslen = 0;
14113498266Sopenharmony_ci    cd = iconv_open_CCSID(dccsid, sccsid, 1);
14213498266Sopenharmony_ci    }
14313498266Sopenharmony_ci  else {
14413498266Sopenharmony_ci    lslen = (size_t) slen;
14513498266Sopenharmony_ci    cd = iconv_open_CCSID(dccsid, sccsid, 0);
14613498266Sopenharmony_ci    }
14713498266Sopenharmony_ci
14813498266Sopenharmony_ci  if(ICONV_OPEN_ERROR(cd))
14913498266Sopenharmony_ci    return -1;
15013498266Sopenharmony_ci
15113498266Sopenharmony_ci  i = dlen;
15213498266Sopenharmony_ci
15313498266Sopenharmony_ci  if((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0)
15413498266Sopenharmony_ci    i = -1;
15513498266Sopenharmony_ci  else
15613498266Sopenharmony_ci    i -= dlen;
15713498266Sopenharmony_ci
15813498266Sopenharmony_ci  iconv_close(cd);
15913498266Sopenharmony_ci  return i;
16013498266Sopenharmony_ci}
16113498266Sopenharmony_ci
16213498266Sopenharmony_ci
16313498266Sopenharmony_cistatic char *dynconvert(int dccsid, const char *s, int slen, int sccsid)
16413498266Sopenharmony_ci{
16513498266Sopenharmony_ci  char *d;
16613498266Sopenharmony_ci  char *cp;
16713498266Sopenharmony_ci  size_t dlen;
16813498266Sopenharmony_ci  int l;
16913498266Sopenharmony_ci  static const char nullbyte = 0;
17013498266Sopenharmony_ci
17113498266Sopenharmony_ci  /* Like convert, but the destination is allocated and returned. */
17213498266Sopenharmony_ci
17313498266Sopenharmony_ci  dlen = (size_t) (slen < 0? strlen(s): slen) + 1;
17413498266Sopenharmony_ci  dlen *= MAX_CONV_EXPANSION;           /* Allow some expansion. */
17513498266Sopenharmony_ci  d = malloc(dlen);
17613498266Sopenharmony_ci
17713498266Sopenharmony_ci  if(!d)
17813498266Sopenharmony_ci    return (char *) NULL;
17913498266Sopenharmony_ci
18013498266Sopenharmony_ci  l = convert(d, dlen, dccsid, s, slen, sccsid);
18113498266Sopenharmony_ci
18213498266Sopenharmony_ci  if(l < 0) {
18313498266Sopenharmony_ci    free(d);
18413498266Sopenharmony_ci    return (char *) NULL;
18513498266Sopenharmony_ci    }
18613498266Sopenharmony_ci
18713498266Sopenharmony_ci  if(slen < 0) {
18813498266Sopenharmony_ci    /* Need to null-terminate even when source length is given.
18913498266Sopenharmony_ci       Since destination code size is unknown, use a conversion to generate
19013498266Sopenharmony_ci       terminator. */
19113498266Sopenharmony_ci
19213498266Sopenharmony_ci    int l2 = convert(d + l, dlen - l, dccsid, &nullbyte, -1, ASCII_CCSID);
19313498266Sopenharmony_ci
19413498266Sopenharmony_ci    if(l2 < 0) {
19513498266Sopenharmony_ci      free(d);
19613498266Sopenharmony_ci      return (char *) NULL;
19713498266Sopenharmony_ci      }
19813498266Sopenharmony_ci
19913498266Sopenharmony_ci    l += l2;
20013498266Sopenharmony_ci    }
20113498266Sopenharmony_ci
20213498266Sopenharmony_ci  if((size_t) l < dlen) {
20313498266Sopenharmony_ci    cp = realloc(d, l);         /* Shorten to minimum needed. */
20413498266Sopenharmony_ci
20513498266Sopenharmony_ci    if(cp)
20613498266Sopenharmony_ci      d = cp;
20713498266Sopenharmony_ci    }
20813498266Sopenharmony_ci
20913498266Sopenharmony_ci  return d;
21013498266Sopenharmony_ci}
21113498266Sopenharmony_ci
21213498266Sopenharmony_ci
21313498266Sopenharmony_cistatic struct curl_slist *
21413498266Sopenharmony_cislist_convert(int dccsid, struct curl_slist *from, int sccsid)
21513498266Sopenharmony_ci{
21613498266Sopenharmony_ci  struct curl_slist *to = (struct curl_slist *) NULL;
21713498266Sopenharmony_ci
21813498266Sopenharmony_ci  for(; from; from = from->next) {
21913498266Sopenharmony_ci    struct curl_slist *nl;
22013498266Sopenharmony_ci    char *cp = dynconvert(dccsid, from->data, -1, sccsid);
22113498266Sopenharmony_ci
22213498266Sopenharmony_ci    if(!cp) {
22313498266Sopenharmony_ci      curl_slist_free_all(to);
22413498266Sopenharmony_ci      return (struct curl_slist *) NULL;
22513498266Sopenharmony_ci    }
22613498266Sopenharmony_ci    nl = Curl_slist_append_nodup(to, cp);
22713498266Sopenharmony_ci    if(!nl) {
22813498266Sopenharmony_ci      curl_slist_free_all(to);
22913498266Sopenharmony_ci      free(cp);
23013498266Sopenharmony_ci      return NULL;
23113498266Sopenharmony_ci    }
23213498266Sopenharmony_ci    to = nl;
23313498266Sopenharmony_ci  }
23413498266Sopenharmony_ci  return to;
23513498266Sopenharmony_ci}
23613498266Sopenharmony_ci
23713498266Sopenharmony_ci
23813498266Sopenharmony_cistatic char *
23913498266Sopenharmony_cikeyed_string(localkey_t key, const char *ascii, unsigned int ccsid)
24013498266Sopenharmony_ci{
24113498266Sopenharmony_ci  int i;
24213498266Sopenharmony_ci  char *ebcdic;
24313498266Sopenharmony_ci
24413498266Sopenharmony_ci  if(!ascii)
24513498266Sopenharmony_ci    return (char *) NULL;
24613498266Sopenharmony_ci
24713498266Sopenharmony_ci  i = MAX_CONV_EXPANSION * (strlen(ascii) + 1);
24813498266Sopenharmony_ci
24913498266Sopenharmony_ci  ebcdic = Curl_thread_buffer(key, i);
25013498266Sopenharmony_ci  if(!ebcdic)
25113498266Sopenharmony_ci    return ebcdic;
25213498266Sopenharmony_ci
25313498266Sopenharmony_ci  if(convert(ebcdic, i, ccsid, ascii, -1, ASCII_CCSID) < 0)
25413498266Sopenharmony_ci    return (char *) NULL;
25513498266Sopenharmony_ci
25613498266Sopenharmony_ci  return ebcdic;
25713498266Sopenharmony_ci}
25813498266Sopenharmony_ci
25913498266Sopenharmony_ci
26013498266Sopenharmony_ciconst char *
26113498266Sopenharmony_cicurl_to_ccsid(const char *s, unsigned int ccsid)
26213498266Sopenharmony_ci{
26313498266Sopenharmony_ci  if(s)
26413498266Sopenharmony_ci    s = dynconvert(ccsid, s, -1, ASCII_CCSID);
26513498266Sopenharmony_ci  return s;
26613498266Sopenharmony_ci}
26713498266Sopenharmony_ci
26813498266Sopenharmony_ci
26913498266Sopenharmony_ciconst char *
27013498266Sopenharmony_cicurl_from_ccsid(const char *s, unsigned int ccsid)
27113498266Sopenharmony_ci{
27213498266Sopenharmony_ci  if(s)
27313498266Sopenharmony_ci    s = dynconvert(ASCII_CCSID, s, -1, ccsid);
27413498266Sopenharmony_ci  return s;
27513498266Sopenharmony_ci}
27613498266Sopenharmony_ci
27713498266Sopenharmony_ci
27813498266Sopenharmony_cichar *
27913498266Sopenharmony_cicurl_version_ccsid(unsigned int ccsid)
28013498266Sopenharmony_ci{
28113498266Sopenharmony_ci  return keyed_string(LK_CURL_VERSION, curl_version(), ccsid);
28213498266Sopenharmony_ci}
28313498266Sopenharmony_ci
28413498266Sopenharmony_ci
28513498266Sopenharmony_cichar *
28613498266Sopenharmony_cicurl_easy_escape_ccsid(CURL *handle, const char *string, int length,
28713498266Sopenharmony_ci                       unsigned int sccsid, unsigned int dccsid)
28813498266Sopenharmony_ci{
28913498266Sopenharmony_ci  char *s;
29013498266Sopenharmony_ci  char *d;
29113498266Sopenharmony_ci
29213498266Sopenharmony_ci  if(!string) {
29313498266Sopenharmony_ci    errno = EINVAL;
29413498266Sopenharmony_ci    return (char *) NULL;
29513498266Sopenharmony_ci    }
29613498266Sopenharmony_ci
29713498266Sopenharmony_ci  s = dynconvert(ASCII_CCSID, string, length? length: -1, sccsid);
29813498266Sopenharmony_ci
29913498266Sopenharmony_ci  if(!s)
30013498266Sopenharmony_ci    return (char *) NULL;
30113498266Sopenharmony_ci
30213498266Sopenharmony_ci  d = curl_easy_escape(handle, s, 0);
30313498266Sopenharmony_ci  free(s);
30413498266Sopenharmony_ci
30513498266Sopenharmony_ci  if(!d)
30613498266Sopenharmony_ci    return (char *) NULL;
30713498266Sopenharmony_ci
30813498266Sopenharmony_ci  s = dynconvert(dccsid, d, -1, ASCII_CCSID);
30913498266Sopenharmony_ci  free(d);
31013498266Sopenharmony_ci  return s;
31113498266Sopenharmony_ci}
31213498266Sopenharmony_ci
31313498266Sopenharmony_ci
31413498266Sopenharmony_cichar *
31513498266Sopenharmony_cicurl_easy_unescape_ccsid(CURL *handle, const char *string, int length,
31613498266Sopenharmony_ci                         int *outlength,
31713498266Sopenharmony_ci                         unsigned int sccsid, unsigned int dccsid)
31813498266Sopenharmony_ci{
31913498266Sopenharmony_ci  char *s;
32013498266Sopenharmony_ci  char *d;
32113498266Sopenharmony_ci
32213498266Sopenharmony_ci  if(!string) {
32313498266Sopenharmony_ci    errno = EINVAL;
32413498266Sopenharmony_ci    return (char *) NULL;
32513498266Sopenharmony_ci    }
32613498266Sopenharmony_ci
32713498266Sopenharmony_ci  s = dynconvert(ASCII_CCSID, string, length? length: -1, sccsid);
32813498266Sopenharmony_ci
32913498266Sopenharmony_ci  if(!s)
33013498266Sopenharmony_ci    return (char *) NULL;
33113498266Sopenharmony_ci
33213498266Sopenharmony_ci  d = curl_easy_unescape(handle, s, 0, outlength);
33313498266Sopenharmony_ci  free(s);
33413498266Sopenharmony_ci
33513498266Sopenharmony_ci  if(!d)
33613498266Sopenharmony_ci    return (char *) NULL;
33713498266Sopenharmony_ci
33813498266Sopenharmony_ci  s = dynconvert(dccsid, d, -1, ASCII_CCSID);
33913498266Sopenharmony_ci  free(d);
34013498266Sopenharmony_ci
34113498266Sopenharmony_ci  if(s && outlength)
34213498266Sopenharmony_ci    *outlength = strlen(s);
34313498266Sopenharmony_ci
34413498266Sopenharmony_ci  return s;
34513498266Sopenharmony_ci}
34613498266Sopenharmony_ci
34713498266Sopenharmony_ci
34813498266Sopenharmony_cistruct curl_slist *
34913498266Sopenharmony_cicurl_slist_append_ccsid(struct curl_slist *list,
35013498266Sopenharmony_ci                        const char *data, unsigned int ccsid)
35113498266Sopenharmony_ci{
35213498266Sopenharmony_ci  char *s;
35313498266Sopenharmony_ci
35413498266Sopenharmony_ci  s = (char *) NULL;
35513498266Sopenharmony_ci
35613498266Sopenharmony_ci  if(!data)
35713498266Sopenharmony_ci    return curl_slist_append(list, data);
35813498266Sopenharmony_ci
35913498266Sopenharmony_ci  s = dynconvert(ASCII_CCSID, data, -1, ccsid);
36013498266Sopenharmony_ci
36113498266Sopenharmony_ci  if(!s)
36213498266Sopenharmony_ci    return (struct curl_slist *) NULL;
36313498266Sopenharmony_ci
36413498266Sopenharmony_ci  list = curl_slist_append(list, s);
36513498266Sopenharmony_ci  free(s);
36613498266Sopenharmony_ci  return list;
36713498266Sopenharmony_ci}
36813498266Sopenharmony_ci
36913498266Sopenharmony_ci
37013498266Sopenharmony_citime_t
37113498266Sopenharmony_cicurl_getdate_ccsid(const char *p, const time_t *unused, unsigned int ccsid)
37213498266Sopenharmony_ci{
37313498266Sopenharmony_ci  char *s;
37413498266Sopenharmony_ci  time_t t;
37513498266Sopenharmony_ci
37613498266Sopenharmony_ci  if(!p)
37713498266Sopenharmony_ci    return curl_getdate(p, unused);
37813498266Sopenharmony_ci
37913498266Sopenharmony_ci  s = dynconvert(ASCII_CCSID, p, -1, ccsid);
38013498266Sopenharmony_ci
38113498266Sopenharmony_ci  if(!s)
38213498266Sopenharmony_ci    return (time_t) -1;
38313498266Sopenharmony_ci
38413498266Sopenharmony_ci  t = curl_getdate(s, unused);
38513498266Sopenharmony_ci  free(s);
38613498266Sopenharmony_ci  return t;
38713498266Sopenharmony_ci}
38813498266Sopenharmony_ci
38913498266Sopenharmony_ci
39013498266Sopenharmony_cistatic int
39113498266Sopenharmony_ciconvert_version_info_string(const char **stringp,
39213498266Sopenharmony_ci                            char **bufp, int *left, unsigned int ccsid)
39313498266Sopenharmony_ci{
39413498266Sopenharmony_ci  /* Helper for curl_version_info_ccsid(): convert a string if defined.
39513498266Sopenharmony_ci     Result is stored in the `*left'-byte buffer at `*bufp'.
39613498266Sopenharmony_ci     `*bufp' and `*left' are updated accordingly.
39713498266Sopenharmony_ci     Return 0 if ok, else -1. */
39813498266Sopenharmony_ci
39913498266Sopenharmony_ci  if(*stringp) {
40013498266Sopenharmony_ci    int l = convert(*bufp, *left, ccsid, *stringp, -1, ASCII_CCSID);
40113498266Sopenharmony_ci
40213498266Sopenharmony_ci    if(l <= 0)
40313498266Sopenharmony_ci      return -1;
40413498266Sopenharmony_ci
40513498266Sopenharmony_ci    *stringp = *bufp;
40613498266Sopenharmony_ci    *bufp += l;
40713498266Sopenharmony_ci    *left -= l;
40813498266Sopenharmony_ci    }
40913498266Sopenharmony_ci
41013498266Sopenharmony_ci  return 0;
41113498266Sopenharmony_ci}
41213498266Sopenharmony_ci
41313498266Sopenharmony_ci
41413498266Sopenharmony_cicurl_version_info_data *
41513498266Sopenharmony_cicurl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
41613498266Sopenharmony_ci{
41713498266Sopenharmony_ci  curl_version_info_data *p;
41813498266Sopenharmony_ci  char *cp;
41913498266Sopenharmony_ci  int n;
42013498266Sopenharmony_ci  int nproto;
42113498266Sopenharmony_ci  curl_version_info_data *id;
42213498266Sopenharmony_ci  int i;
42313498266Sopenharmony_ci  const char **cpp;
42413498266Sopenharmony_ci  static const size_t charfields[] = {
42513498266Sopenharmony_ci    offsetof(curl_version_info_data, version),
42613498266Sopenharmony_ci    offsetof(curl_version_info_data, host),
42713498266Sopenharmony_ci    offsetof(curl_version_info_data, ssl_version),
42813498266Sopenharmony_ci    offsetof(curl_version_info_data, libz_version),
42913498266Sopenharmony_ci    offsetof(curl_version_info_data, ares),
43013498266Sopenharmony_ci    offsetof(curl_version_info_data, libidn),
43113498266Sopenharmony_ci    offsetof(curl_version_info_data, libssh_version),
43213498266Sopenharmony_ci    offsetof(curl_version_info_data, brotli_version),
43313498266Sopenharmony_ci    offsetof(curl_version_info_data, nghttp2_version),
43413498266Sopenharmony_ci    offsetof(curl_version_info_data, quic_version),
43513498266Sopenharmony_ci    offsetof(curl_version_info_data, cainfo),
43613498266Sopenharmony_ci    offsetof(curl_version_info_data, capath),
43713498266Sopenharmony_ci    offsetof(curl_version_info_data, zstd_version),
43813498266Sopenharmony_ci    offsetof(curl_version_info_data, hyper_version),
43913498266Sopenharmony_ci    offsetof(curl_version_info_data, gsasl_version),
44013498266Sopenharmony_ci    offsetof(curl_version_info_data, feature_names)
44113498266Sopenharmony_ci  };
44213498266Sopenharmony_ci
44313498266Sopenharmony_ci  /* The assertion below is possible, because although the second operand
44413498266Sopenharmony_ci     is an enum member, the first is a #define. In that case, the OS/400 C
44513498266Sopenharmony_ci     compiler seems to compare string values after substitution. */
44613498266Sopenharmony_ci
44713498266Sopenharmony_ci#if CURLVERSION_NOW != CURLVERSION_ELEVENTH
44813498266Sopenharmony_ci#error curl_version_info_data structure has changed: upgrade this procedure.
44913498266Sopenharmony_ci#endif
45013498266Sopenharmony_ci
45113498266Sopenharmony_ci  /* If caller has been compiled with a newer version, error. */
45213498266Sopenharmony_ci
45313498266Sopenharmony_ci  if(stamp > CURLVERSION_NOW)
45413498266Sopenharmony_ci    return (curl_version_info_data *) NULL;
45513498266Sopenharmony_ci
45613498266Sopenharmony_ci  p = curl_version_info(stamp);
45713498266Sopenharmony_ci
45813498266Sopenharmony_ci  if(!p)
45913498266Sopenharmony_ci    return p;
46013498266Sopenharmony_ci
46113498266Sopenharmony_ci  /* Measure thread space needed. */
46213498266Sopenharmony_ci
46313498266Sopenharmony_ci  n = 0;
46413498266Sopenharmony_ci  nproto = 0;
46513498266Sopenharmony_ci
46613498266Sopenharmony_ci  if(p->protocols) {
46713498266Sopenharmony_ci    while(p->protocols[nproto])
46813498266Sopenharmony_ci      n += strlen(p->protocols[nproto++]);
46913498266Sopenharmony_ci
47013498266Sopenharmony_ci    n += nproto++;
47113498266Sopenharmony_ci    }
47213498266Sopenharmony_ci
47313498266Sopenharmony_ci  for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) {
47413498266Sopenharmony_ci    cpp = (const char **) ((char *) p + charfields[i]);
47513498266Sopenharmony_ci    if(*cpp)
47613498266Sopenharmony_ci      n += strlen(*cpp) + 1;
47713498266Sopenharmony_ci  }
47813498266Sopenharmony_ci
47913498266Sopenharmony_ci  /* Allocate thread space. */
48013498266Sopenharmony_ci
48113498266Sopenharmony_ci  n *= MAX_CONV_EXPANSION;
48213498266Sopenharmony_ci
48313498266Sopenharmony_ci  if(nproto)
48413498266Sopenharmony_ci    n += nproto * sizeof(const char *);
48513498266Sopenharmony_ci
48613498266Sopenharmony_ci  cp = Curl_thread_buffer(LK_VERSION_INFO_DATA, n);
48713498266Sopenharmony_ci  id = (curl_version_info_data *) Curl_thread_buffer(LK_VERSION_INFO,
48813498266Sopenharmony_ci                                                     sizeof(*id));
48913498266Sopenharmony_ci
49013498266Sopenharmony_ci  if(!id || !cp)
49113498266Sopenharmony_ci    return (curl_version_info_data *) NULL;
49213498266Sopenharmony_ci
49313498266Sopenharmony_ci  /* Copy data and convert strings. */
49413498266Sopenharmony_ci
49513498266Sopenharmony_ci  memcpy((char *) id, (char *) p, sizeof(*p));
49613498266Sopenharmony_ci
49713498266Sopenharmony_ci  if(id->protocols) {
49813498266Sopenharmony_ci    i = nproto * sizeof(id->protocols[0]);
49913498266Sopenharmony_ci
50013498266Sopenharmony_ci    id->protocols = (const char * const *) cp;
50113498266Sopenharmony_ci    memcpy(cp, (char *) p->protocols, i);
50213498266Sopenharmony_ci    cp += i;
50313498266Sopenharmony_ci    n -= i;
50413498266Sopenharmony_ci
50513498266Sopenharmony_ci    for(i = 0; id->protocols[i]; i++)
50613498266Sopenharmony_ci      if(convert_version_info_string(((const char * *) id->protocols) + i,
50713498266Sopenharmony_ci                                      &cp, &n, ccsid))
50813498266Sopenharmony_ci        return (curl_version_info_data *) NULL;
50913498266Sopenharmony_ci  }
51013498266Sopenharmony_ci
51113498266Sopenharmony_ci  for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) {
51213498266Sopenharmony_ci    cpp = (const char **) ((char *) p + charfields[i]);
51313498266Sopenharmony_ci    if(*cpp && convert_version_info_string(cpp, &cp, &n, ccsid))
51413498266Sopenharmony_ci      return (curl_version_info_data *) NULL;
51513498266Sopenharmony_ci  }
51613498266Sopenharmony_ci
51713498266Sopenharmony_ci  return id;
51813498266Sopenharmony_ci}
51913498266Sopenharmony_ci
52013498266Sopenharmony_ci
52113498266Sopenharmony_ciconst char *
52213498266Sopenharmony_cicurl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid)
52313498266Sopenharmony_ci{
52413498266Sopenharmony_ci  return keyed_string(LK_EASY_STRERROR, curl_easy_strerror(error), ccsid);
52513498266Sopenharmony_ci}
52613498266Sopenharmony_ci
52713498266Sopenharmony_ci
52813498266Sopenharmony_ciconst char *
52913498266Sopenharmony_cicurl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid)
53013498266Sopenharmony_ci{
53113498266Sopenharmony_ci  return keyed_string(LK_SHARE_STRERROR, curl_share_strerror(error), ccsid);
53213498266Sopenharmony_ci}
53313498266Sopenharmony_ci
53413498266Sopenharmony_ci
53513498266Sopenharmony_ciconst char *
53613498266Sopenharmony_cicurl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid)
53713498266Sopenharmony_ci{
53813498266Sopenharmony_ci  return keyed_string(LK_MULTI_STRERROR, curl_multi_strerror(error), ccsid);
53913498266Sopenharmony_ci}
54013498266Sopenharmony_ci
54113498266Sopenharmony_ci
54213498266Sopenharmony_ciconst char *
54313498266Sopenharmony_cicurl_url_strerror_ccsid(CURLUcode error, unsigned int ccsid)
54413498266Sopenharmony_ci{
54513498266Sopenharmony_ci  return keyed_string(LK_URL_STRERROR, curl_url_strerror(error), ccsid);
54613498266Sopenharmony_ci}
54713498266Sopenharmony_ci
54813498266Sopenharmony_ci
54913498266Sopenharmony_civoid
55013498266Sopenharmony_cicurl_certinfo_free_all(struct curl_certinfo *info)
55113498266Sopenharmony_ci{
55213498266Sopenharmony_ci  /* Free all memory used by certificate info. */
55313498266Sopenharmony_ci  if(info) {
55413498266Sopenharmony_ci    if(info->certinfo) {
55513498266Sopenharmony_ci      int i;
55613498266Sopenharmony_ci
55713498266Sopenharmony_ci      for(i = 0; i < info->num_of_certs; i++)
55813498266Sopenharmony_ci        curl_slist_free_all(info->certinfo[i]);
55913498266Sopenharmony_ci      free((char *) info->certinfo);
56013498266Sopenharmony_ci    }
56113498266Sopenharmony_ci    free((char *) info);
56213498266Sopenharmony_ci  }
56313498266Sopenharmony_ci}
56413498266Sopenharmony_ci
56513498266Sopenharmony_ci
56613498266Sopenharmony_ciCURLcode
56713498266Sopenharmony_cicurl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...)
56813498266Sopenharmony_ci{
56913498266Sopenharmony_ci  va_list arg;
57013498266Sopenharmony_ci  void *paramp;
57113498266Sopenharmony_ci  CURLcode ret;
57213498266Sopenharmony_ci  struct Curl_easy *data;
57313498266Sopenharmony_ci
57413498266Sopenharmony_ci  /* WARNING: unlike curl_easy_getinfo(), the strings returned by this
57513498266Sopenharmony_ci     procedure have to be free'ed. */
57613498266Sopenharmony_ci
57713498266Sopenharmony_ci  data = (struct Curl_easy *) curl;
57813498266Sopenharmony_ci  va_start(arg, info);
57913498266Sopenharmony_ci  paramp = va_arg(arg, void *);
58013498266Sopenharmony_ci  ret = Curl_getinfo(data, info, paramp);
58113498266Sopenharmony_ci
58213498266Sopenharmony_ci  if(ret == CURLE_OK) {
58313498266Sopenharmony_ci    unsigned int ccsid;
58413498266Sopenharmony_ci    char **cpp;
58513498266Sopenharmony_ci    struct curl_slist **slp;
58613498266Sopenharmony_ci    struct curl_certinfo *cipf;
58713498266Sopenharmony_ci    struct curl_certinfo *cipt;
58813498266Sopenharmony_ci
58913498266Sopenharmony_ci    switch((int) info & CURLINFO_TYPEMASK) {
59013498266Sopenharmony_ci
59113498266Sopenharmony_ci    case CURLINFO_STRING:
59213498266Sopenharmony_ci      ccsid = va_arg(arg, unsigned int);
59313498266Sopenharmony_ci      cpp = (char * *) paramp;
59413498266Sopenharmony_ci
59513498266Sopenharmony_ci      if(*cpp) {
59613498266Sopenharmony_ci        *cpp = dynconvert(ccsid, *cpp, -1, ASCII_CCSID);
59713498266Sopenharmony_ci
59813498266Sopenharmony_ci        if(!*cpp)
59913498266Sopenharmony_ci          ret = CURLE_OUT_OF_MEMORY;
60013498266Sopenharmony_ci      }
60113498266Sopenharmony_ci
60213498266Sopenharmony_ci      break;
60313498266Sopenharmony_ci
60413498266Sopenharmony_ci    case CURLINFO_SLIST:
60513498266Sopenharmony_ci      ccsid = va_arg(arg, unsigned int);
60613498266Sopenharmony_ci      switch(info) {
60713498266Sopenharmony_ci      case CURLINFO_CERTINFO:
60813498266Sopenharmony_ci        cipf = *(struct curl_certinfo * *) paramp;
60913498266Sopenharmony_ci        if(cipf) {
61013498266Sopenharmony_ci          cipt = (struct curl_certinfo *) malloc(sizeof(*cipt));
61113498266Sopenharmony_ci          if(!cipt)
61213498266Sopenharmony_ci            ret = CURLE_OUT_OF_MEMORY;
61313498266Sopenharmony_ci          else {
61413498266Sopenharmony_ci            cipt->certinfo = (struct curl_slist **)
61513498266Sopenharmony_ci              calloc(cipf->num_of_certs +
61613498266Sopenharmony_ci                     1, sizeof(struct curl_slist *));
61713498266Sopenharmony_ci            if(!cipt->certinfo)
61813498266Sopenharmony_ci              ret = CURLE_OUT_OF_MEMORY;
61913498266Sopenharmony_ci            else {
62013498266Sopenharmony_ci              int i;
62113498266Sopenharmony_ci
62213498266Sopenharmony_ci              cipt->num_of_certs = cipf->num_of_certs;
62313498266Sopenharmony_ci              for(i = 0; i < cipf->num_of_certs; i++)
62413498266Sopenharmony_ci                if(cipf->certinfo[i])
62513498266Sopenharmony_ci                  if(!(cipt->certinfo[i] = slist_convert(ccsid,
62613498266Sopenharmony_ci                                                          cipf->certinfo[i],
62713498266Sopenharmony_ci                                                          ASCII_CCSID))) {
62813498266Sopenharmony_ci                    ret = CURLE_OUT_OF_MEMORY;
62913498266Sopenharmony_ci                    break;
63013498266Sopenharmony_ci                  }
63113498266Sopenharmony_ci              }
63213498266Sopenharmony_ci            }
63313498266Sopenharmony_ci
63413498266Sopenharmony_ci          if(ret != CURLE_OK) {
63513498266Sopenharmony_ci            curl_certinfo_free_all(cipt);
63613498266Sopenharmony_ci            cipt = (struct curl_certinfo *) NULL;
63713498266Sopenharmony_ci          }
63813498266Sopenharmony_ci
63913498266Sopenharmony_ci          *(struct curl_certinfo * *) paramp = cipt;
64013498266Sopenharmony_ci        }
64113498266Sopenharmony_ci
64213498266Sopenharmony_ci        break;
64313498266Sopenharmony_ci
64413498266Sopenharmony_ci      case CURLINFO_TLS_SESSION:
64513498266Sopenharmony_ci      case CURLINFO_TLS_SSL_PTR:
64613498266Sopenharmony_ci      case CURLINFO_SOCKET:
64713498266Sopenharmony_ci        break;
64813498266Sopenharmony_ci
64913498266Sopenharmony_ci      default:
65013498266Sopenharmony_ci        slp = (struct curl_slist **) paramp;
65113498266Sopenharmony_ci        if(*slp) {
65213498266Sopenharmony_ci          *slp = slist_convert(ccsid, *slp, ASCII_CCSID);
65313498266Sopenharmony_ci          if(!*slp)
65413498266Sopenharmony_ci            ret = CURLE_OUT_OF_MEMORY;
65513498266Sopenharmony_ci        }
65613498266Sopenharmony_ci        break;
65713498266Sopenharmony_ci      }
65813498266Sopenharmony_ci    }
65913498266Sopenharmony_ci  }
66013498266Sopenharmony_ci
66113498266Sopenharmony_ci  va_end(arg);
66213498266Sopenharmony_ci  return ret;
66313498266Sopenharmony_ci}
66413498266Sopenharmony_ci
66513498266Sopenharmony_ci
66613498266Sopenharmony_cistatic int
66713498266Sopenharmony_ciCurl_is_formadd_string(CURLformoption option)
66813498266Sopenharmony_ci{
66913498266Sopenharmony_ci  switch(option) {
67013498266Sopenharmony_ci
67113498266Sopenharmony_ci  case CURLFORM_FILENAME:
67213498266Sopenharmony_ci  case CURLFORM_CONTENTTYPE:
67313498266Sopenharmony_ci  case CURLFORM_BUFFER:
67413498266Sopenharmony_ci  case CURLFORM_FILE:
67513498266Sopenharmony_ci  case CURLFORM_FILECONTENT:
67613498266Sopenharmony_ci  case CURLFORM_COPYCONTENTS:
67713498266Sopenharmony_ci  case CURLFORM_COPYNAME:
67813498266Sopenharmony_ci    return 1;
67913498266Sopenharmony_ci  }
68013498266Sopenharmony_ci
68113498266Sopenharmony_ci  return 0;
68213498266Sopenharmony_ci}
68313498266Sopenharmony_ci
68413498266Sopenharmony_ci
68513498266Sopenharmony_cistatic void
68613498266Sopenharmony_ciCurl_formadd_release_local(struct curl_forms *forms, int nargs, int skip)
68713498266Sopenharmony_ci{
68813498266Sopenharmony_ci  while(nargs--)
68913498266Sopenharmony_ci    if(nargs != skip)
69013498266Sopenharmony_ci      if(Curl_is_formadd_string(forms[nargs].option))
69113498266Sopenharmony_ci        if(forms[nargs].value)
69213498266Sopenharmony_ci          free((char *) forms[nargs].value);
69313498266Sopenharmony_ci
69413498266Sopenharmony_ci  free((char *) forms);
69513498266Sopenharmony_ci}
69613498266Sopenharmony_ci
69713498266Sopenharmony_ci
69813498266Sopenharmony_cistatic int
69913498266Sopenharmony_ciCurl_formadd_convert(struct curl_forms *forms,
70013498266Sopenharmony_ci                     int formx, int lengthx, unsigned int ccsid)
70113498266Sopenharmony_ci{
70213498266Sopenharmony_ci  int l;
70313498266Sopenharmony_ci  char *cp;
70413498266Sopenharmony_ci  char *cp2;
70513498266Sopenharmony_ci
70613498266Sopenharmony_ci  if(formx < 0 || !forms[formx].value)
70713498266Sopenharmony_ci    return 0;
70813498266Sopenharmony_ci
70913498266Sopenharmony_ci  if(lengthx >= 0)
71013498266Sopenharmony_ci    l = (int) forms[lengthx].value;
71113498266Sopenharmony_ci  else
71213498266Sopenharmony_ci    l = strlen(forms[formx].value) + 1;
71313498266Sopenharmony_ci
71413498266Sopenharmony_ci  cp = malloc(MAX_CONV_EXPANSION * l);
71513498266Sopenharmony_ci
71613498266Sopenharmony_ci  if(!cp)
71713498266Sopenharmony_ci    return -1;
71813498266Sopenharmony_ci
71913498266Sopenharmony_ci  l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID,
72013498266Sopenharmony_ci              forms[formx].value, l, ccsid);
72113498266Sopenharmony_ci
72213498266Sopenharmony_ci  if(l < 0) {
72313498266Sopenharmony_ci    free(cp);
72413498266Sopenharmony_ci    return -1;
72513498266Sopenharmony_ci    }
72613498266Sopenharmony_ci
72713498266Sopenharmony_ci  cp2 = realloc(cp, l);         /* Shorten buffer to the string size. */
72813498266Sopenharmony_ci
72913498266Sopenharmony_ci  if(cp2)
73013498266Sopenharmony_ci    cp = cp2;
73113498266Sopenharmony_ci
73213498266Sopenharmony_ci  forms[formx].value = cp;
73313498266Sopenharmony_ci
73413498266Sopenharmony_ci  if(lengthx >= 0)
73513498266Sopenharmony_ci    forms[lengthx].value = (char *) l;  /* Update length after conversion. */
73613498266Sopenharmony_ci
73713498266Sopenharmony_ci  return l;
73813498266Sopenharmony_ci}
73913498266Sopenharmony_ci
74013498266Sopenharmony_ci
74113498266Sopenharmony_ciCURLFORMcode
74213498266Sopenharmony_cicurl_formadd_ccsid(struct curl_httppost **httppost,
74313498266Sopenharmony_ci                   struct curl_httppost **last_post, ...)
74413498266Sopenharmony_ci{
74513498266Sopenharmony_ci  va_list arg;
74613498266Sopenharmony_ci  CURLformoption option;
74713498266Sopenharmony_ci  CURLFORMcode result;
74813498266Sopenharmony_ci  struct curl_forms *forms;
74913498266Sopenharmony_ci  struct curl_forms *lforms;
75013498266Sopenharmony_ci  struct curl_forms *tforms;
75113498266Sopenharmony_ci  unsigned int lformlen;
75213498266Sopenharmony_ci  const char *value;
75313498266Sopenharmony_ci  unsigned int ccsid;
75413498266Sopenharmony_ci  int nargs;
75513498266Sopenharmony_ci  int namex;
75613498266Sopenharmony_ci  int namelengthx;
75713498266Sopenharmony_ci  int contentx;
75813498266Sopenharmony_ci  int lengthx;
75913498266Sopenharmony_ci  unsigned int contentccsid;
76013498266Sopenharmony_ci  unsigned int nameccsid;
76113498266Sopenharmony_ci
76213498266Sopenharmony_ci  /* A single curl_formadd() call cannot be split in several calls to deal
76313498266Sopenharmony_ci     with all parameters: the original parameters are thus copied to a local
76413498266Sopenharmony_ci     curl_forms array and converted to ASCII when needed.
76513498266Sopenharmony_ci     CURLFORM_PTRNAME is processed as if it were CURLFORM_COPYNAME.
76613498266Sopenharmony_ci     CURLFORM_COPYNAME and CURLFORM_NAMELENGTH occurrence order in
76713498266Sopenharmony_ci     parameters is not defined; for this reason, the actual conversion is
76813498266Sopenharmony_ci     delayed to the end of parameter processing. The same applies to
76913498266Sopenharmony_ci     CURLFORM_COPYCONTENTS/CURLFORM_CONTENTSLENGTH, but these may appear
77013498266Sopenharmony_ci     several times in the parameter list; the problem resides here in knowing
77113498266Sopenharmony_ci     which CURLFORM_CONTENTSLENGTH applies to which CURLFORM_COPYCONTENTS and
77213498266Sopenharmony_ci     when we can be sure to have both info for conversion: end of parameter
77313498266Sopenharmony_ci     list is such a point, but CURLFORM_CONTENTTYPE is also used here as a
77413498266Sopenharmony_ci     natural separator between content data definitions; this seems to be
77513498266Sopenharmony_ci     in accordance with FormAdd() behavior. */
77613498266Sopenharmony_ci
77713498266Sopenharmony_ci  /* Allocate the local curl_forms array. */
77813498266Sopenharmony_ci
77913498266Sopenharmony_ci  lformlen = ALLOC_GRANULE;
78013498266Sopenharmony_ci  lforms = malloc(lformlen * sizeof(*lforms));
78113498266Sopenharmony_ci
78213498266Sopenharmony_ci  if(!lforms)
78313498266Sopenharmony_ci    return CURL_FORMADD_MEMORY;
78413498266Sopenharmony_ci
78513498266Sopenharmony_ci  /* Process the arguments, copying them into local array, latching conversion
78613498266Sopenharmony_ci     indexes and converting when needed. */
78713498266Sopenharmony_ci
78813498266Sopenharmony_ci  result = CURL_FORMADD_OK;
78913498266Sopenharmony_ci  nargs = 0;
79013498266Sopenharmony_ci  contentx = -1;
79113498266Sopenharmony_ci  lengthx = -1;
79213498266Sopenharmony_ci  namex = -1;
79313498266Sopenharmony_ci  namelengthx = -1;
79413498266Sopenharmony_ci  forms = (struct curl_forms *) NULL;
79513498266Sopenharmony_ci  va_start(arg, last_post);
79613498266Sopenharmony_ci
79713498266Sopenharmony_ci  for(;;) {
79813498266Sopenharmony_ci    /* Make sure there is still room for an item in local array. */
79913498266Sopenharmony_ci
80013498266Sopenharmony_ci    if(nargs >= lformlen) {
80113498266Sopenharmony_ci      lformlen += ALLOC_GRANULE;
80213498266Sopenharmony_ci      tforms = realloc(lforms, lformlen * sizeof(*lforms));
80313498266Sopenharmony_ci
80413498266Sopenharmony_ci      if(!tforms) {
80513498266Sopenharmony_ci        result = CURL_FORMADD_MEMORY;
80613498266Sopenharmony_ci        break;
80713498266Sopenharmony_ci        }
80813498266Sopenharmony_ci
80913498266Sopenharmony_ci      lforms = tforms;
81013498266Sopenharmony_ci      }
81113498266Sopenharmony_ci
81213498266Sopenharmony_ci    /* Get next option. */
81313498266Sopenharmony_ci
81413498266Sopenharmony_ci    if(forms) {
81513498266Sopenharmony_ci      /* Get option from array. */
81613498266Sopenharmony_ci
81713498266Sopenharmony_ci      option = forms->option;
81813498266Sopenharmony_ci      value = forms->value;
81913498266Sopenharmony_ci      forms++;
82013498266Sopenharmony_ci      }
82113498266Sopenharmony_ci    else {
82213498266Sopenharmony_ci      /* Get option from arguments. */
82313498266Sopenharmony_ci
82413498266Sopenharmony_ci      option = va_arg(arg, CURLformoption);
82513498266Sopenharmony_ci
82613498266Sopenharmony_ci      if(option == CURLFORM_END)
82713498266Sopenharmony_ci        break;
82813498266Sopenharmony_ci      }
82913498266Sopenharmony_ci
83013498266Sopenharmony_ci    /* Dispatch by option. */
83113498266Sopenharmony_ci
83213498266Sopenharmony_ci    switch(option) {
83313498266Sopenharmony_ci
83413498266Sopenharmony_ci    case CURLFORM_END:
83513498266Sopenharmony_ci      forms = (struct curl_forms *) NULL;       /* Leave array mode. */
83613498266Sopenharmony_ci      continue;
83713498266Sopenharmony_ci
83813498266Sopenharmony_ci    case CURLFORM_ARRAY:
83913498266Sopenharmony_ci      if(!forms) {
84013498266Sopenharmony_ci        forms = va_arg(arg, struct curl_forms *);
84113498266Sopenharmony_ci        continue;
84213498266Sopenharmony_ci        }
84313498266Sopenharmony_ci
84413498266Sopenharmony_ci      result = CURL_FORMADD_ILLEGAL_ARRAY;
84513498266Sopenharmony_ci      break;
84613498266Sopenharmony_ci
84713498266Sopenharmony_ci    case CURLFORM_COPYNAME:
84813498266Sopenharmony_ci      option = CURLFORM_PTRNAME;                /* Static for now. */
84913498266Sopenharmony_ci
85013498266Sopenharmony_ci    case CURLFORM_PTRNAME:
85113498266Sopenharmony_ci      if(namex >= 0)
85213498266Sopenharmony_ci        result = CURL_FORMADD_OPTION_TWICE;
85313498266Sopenharmony_ci
85413498266Sopenharmony_ci      namex = nargs;
85513498266Sopenharmony_ci
85613498266Sopenharmony_ci      if(!forms) {
85713498266Sopenharmony_ci        value = va_arg(arg, char *);
85813498266Sopenharmony_ci        nameccsid = (unsigned int) va_arg(arg, long);
85913498266Sopenharmony_ci        }
86013498266Sopenharmony_ci      else {
86113498266Sopenharmony_ci        nameccsid = (unsigned int) forms->value;
86213498266Sopenharmony_ci        forms++;
86313498266Sopenharmony_ci        }
86413498266Sopenharmony_ci
86513498266Sopenharmony_ci      break;
86613498266Sopenharmony_ci
86713498266Sopenharmony_ci    case CURLFORM_COPYCONTENTS:
86813498266Sopenharmony_ci      if(contentx >= 0)
86913498266Sopenharmony_ci        result = CURL_FORMADD_OPTION_TWICE;
87013498266Sopenharmony_ci
87113498266Sopenharmony_ci      contentx = nargs;
87213498266Sopenharmony_ci
87313498266Sopenharmony_ci      if(!forms) {
87413498266Sopenharmony_ci        value = va_arg(arg, char *);
87513498266Sopenharmony_ci        contentccsid = (unsigned int) va_arg(arg, long);
87613498266Sopenharmony_ci        }
87713498266Sopenharmony_ci      else {
87813498266Sopenharmony_ci        contentccsid = (unsigned int) forms->value;
87913498266Sopenharmony_ci        forms++;
88013498266Sopenharmony_ci        }
88113498266Sopenharmony_ci
88213498266Sopenharmony_ci      break;
88313498266Sopenharmony_ci
88413498266Sopenharmony_ci    case CURLFORM_PTRCONTENTS:
88513498266Sopenharmony_ci    case CURLFORM_BUFFERPTR:
88613498266Sopenharmony_ci      if(!forms)
88713498266Sopenharmony_ci        value = va_arg(arg, char *);            /* No conversion. */
88813498266Sopenharmony_ci
88913498266Sopenharmony_ci      break;
89013498266Sopenharmony_ci
89113498266Sopenharmony_ci    case CURLFORM_CONTENTSLENGTH:
89213498266Sopenharmony_ci      lengthx = nargs;
89313498266Sopenharmony_ci
89413498266Sopenharmony_ci      if(!forms)
89513498266Sopenharmony_ci        value = (char *) va_arg(arg, long);
89613498266Sopenharmony_ci
89713498266Sopenharmony_ci      break;
89813498266Sopenharmony_ci
89913498266Sopenharmony_ci    case CURLFORM_CONTENTLEN:
90013498266Sopenharmony_ci      lengthx = nargs;
90113498266Sopenharmony_ci
90213498266Sopenharmony_ci      if(!forms)
90313498266Sopenharmony_ci        value = (char *) va_arg(arg, curl_off_t);
90413498266Sopenharmony_ci
90513498266Sopenharmony_ci      break;
90613498266Sopenharmony_ci
90713498266Sopenharmony_ci    case CURLFORM_NAMELENGTH:
90813498266Sopenharmony_ci      namelengthx = nargs;
90913498266Sopenharmony_ci
91013498266Sopenharmony_ci      if(!forms)
91113498266Sopenharmony_ci        value = (char *) va_arg(arg, long);
91213498266Sopenharmony_ci
91313498266Sopenharmony_ci      break;
91413498266Sopenharmony_ci
91513498266Sopenharmony_ci    case CURLFORM_BUFFERLENGTH:
91613498266Sopenharmony_ci      if(!forms)
91713498266Sopenharmony_ci        value = (char *) va_arg(arg, long);
91813498266Sopenharmony_ci
91913498266Sopenharmony_ci      break;
92013498266Sopenharmony_ci
92113498266Sopenharmony_ci    case CURLFORM_CONTENTHEADER:
92213498266Sopenharmony_ci      if(!forms)
92313498266Sopenharmony_ci        value = (char *) va_arg(arg, struct curl_slist *);
92413498266Sopenharmony_ci
92513498266Sopenharmony_ci      break;
92613498266Sopenharmony_ci
92713498266Sopenharmony_ci    case CURLFORM_STREAM:
92813498266Sopenharmony_ci      if(!forms)
92913498266Sopenharmony_ci        value = (char *) va_arg(arg, void *);
93013498266Sopenharmony_ci
93113498266Sopenharmony_ci      break;
93213498266Sopenharmony_ci
93313498266Sopenharmony_ci    case CURLFORM_CONTENTTYPE:
93413498266Sopenharmony_ci      /* If a previous content has been encountered, convert it now. */
93513498266Sopenharmony_ci
93613498266Sopenharmony_ci      if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) {
93713498266Sopenharmony_ci        result = CURL_FORMADD_MEMORY;
93813498266Sopenharmony_ci        break;
93913498266Sopenharmony_ci        }
94013498266Sopenharmony_ci
94113498266Sopenharmony_ci      contentx = -1;
94213498266Sopenharmony_ci      lengthx = -1;
94313498266Sopenharmony_ci      /* Fall into default. */
94413498266Sopenharmony_ci
94513498266Sopenharmony_ci    default:
94613498266Sopenharmony_ci      /* Must be a convertible string. */
94713498266Sopenharmony_ci
94813498266Sopenharmony_ci      if(!Curl_is_formadd_string(option)) {
94913498266Sopenharmony_ci        result = CURL_FORMADD_UNKNOWN_OPTION;
95013498266Sopenharmony_ci        break;
95113498266Sopenharmony_ci        }
95213498266Sopenharmony_ci
95313498266Sopenharmony_ci      if(!forms) {
95413498266Sopenharmony_ci        value = va_arg(arg, char *);
95513498266Sopenharmony_ci        ccsid = (unsigned int) va_arg(arg, long);
95613498266Sopenharmony_ci        }
95713498266Sopenharmony_ci      else {
95813498266Sopenharmony_ci        ccsid = (unsigned int) forms->value;
95913498266Sopenharmony_ci        forms++;
96013498266Sopenharmony_ci        }
96113498266Sopenharmony_ci
96213498266Sopenharmony_ci      /* Do the conversion. */
96313498266Sopenharmony_ci
96413498266Sopenharmony_ci      lforms[nargs].value = value;
96513498266Sopenharmony_ci
96613498266Sopenharmony_ci      if(Curl_formadd_convert(lforms, nargs, -1, ccsid) < 0) {
96713498266Sopenharmony_ci        result = CURL_FORMADD_MEMORY;
96813498266Sopenharmony_ci        break;
96913498266Sopenharmony_ci        }
97013498266Sopenharmony_ci
97113498266Sopenharmony_ci      value = lforms[nargs].value;
97213498266Sopenharmony_ci      }
97313498266Sopenharmony_ci
97413498266Sopenharmony_ci    if(result != CURL_FORMADD_OK)
97513498266Sopenharmony_ci      break;
97613498266Sopenharmony_ci
97713498266Sopenharmony_ci    lforms[nargs].value = value;
97813498266Sopenharmony_ci    lforms[nargs++].option = option;
97913498266Sopenharmony_ci    }
98013498266Sopenharmony_ci
98113498266Sopenharmony_ci  va_end(arg);
98213498266Sopenharmony_ci
98313498266Sopenharmony_ci  /* Convert the name and the last content, now that we know their lengths. */
98413498266Sopenharmony_ci
98513498266Sopenharmony_ci  if(result == CURL_FORMADD_OK && namex >= 0) {
98613498266Sopenharmony_ci    if(Curl_formadd_convert(lforms, namex, namelengthx, nameccsid) < 0)
98713498266Sopenharmony_ci      result = CURL_FORMADD_MEMORY;
98813498266Sopenharmony_ci    else
98913498266Sopenharmony_ci      lforms[namex].option = CURLFORM_COPYNAME;         /* Force copy. */
99013498266Sopenharmony_ci    }
99113498266Sopenharmony_ci
99213498266Sopenharmony_ci  if(result == CURL_FORMADD_OK) {
99313498266Sopenharmony_ci    if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0)
99413498266Sopenharmony_ci      result = CURL_FORMADD_MEMORY;
99513498266Sopenharmony_ci    else
99613498266Sopenharmony_ci      contentx = -1;
99713498266Sopenharmony_ci    }
99813498266Sopenharmony_ci
99913498266Sopenharmony_ci  /* Do the formadd with our converted parameters. */
100013498266Sopenharmony_ci
100113498266Sopenharmony_ci  if(result == CURL_FORMADD_OK) {
100213498266Sopenharmony_ci    lforms[nargs].option = CURLFORM_END;
100313498266Sopenharmony_ci    result = curl_formadd(httppost, last_post,
100413498266Sopenharmony_ci                          CURLFORM_ARRAY, lforms, CURLFORM_END);
100513498266Sopenharmony_ci    }
100613498266Sopenharmony_ci
100713498266Sopenharmony_ci  /* Terminate. */
100813498266Sopenharmony_ci
100913498266Sopenharmony_ci  Curl_formadd_release_local(lforms, nargs, contentx);
101013498266Sopenharmony_ci  return result;
101113498266Sopenharmony_ci}
101213498266Sopenharmony_ci
101313498266Sopenharmony_ci
101413498266Sopenharmony_cistruct cfcdata {
101513498266Sopenharmony_ci  curl_formget_callback append;
101613498266Sopenharmony_ci  void *                arg;
101713498266Sopenharmony_ci  unsigned int          ccsid;
101813498266Sopenharmony_ci};
101913498266Sopenharmony_ci
102013498266Sopenharmony_ci
102113498266Sopenharmony_cistatic size_t
102213498266Sopenharmony_ciCurl_formget_callback_ccsid(void *arg, const char *buf, size_t len)
102313498266Sopenharmony_ci{
102413498266Sopenharmony_ci  struct cfcdata *p;
102513498266Sopenharmony_ci  char *b;
102613498266Sopenharmony_ci  int l;
102713498266Sopenharmony_ci  size_t ret;
102813498266Sopenharmony_ci
102913498266Sopenharmony_ci  p = (struct cfcdata *) arg;
103013498266Sopenharmony_ci
103113498266Sopenharmony_ci  if((long) len <= 0)
103213498266Sopenharmony_ci    return (*p->append)(p->arg, buf, len);
103313498266Sopenharmony_ci
103413498266Sopenharmony_ci  b = malloc(MAX_CONV_EXPANSION * len);
103513498266Sopenharmony_ci
103613498266Sopenharmony_ci  if(!b)
103713498266Sopenharmony_ci    return (size_t) -1;
103813498266Sopenharmony_ci
103913498266Sopenharmony_ci  l = convert(b, MAX_CONV_EXPANSION * len, p->ccsid, buf, len, ASCII_CCSID);
104013498266Sopenharmony_ci
104113498266Sopenharmony_ci  if(l < 0) {
104213498266Sopenharmony_ci    free(b);
104313498266Sopenharmony_ci    return (size_t) -1;
104413498266Sopenharmony_ci    }
104513498266Sopenharmony_ci
104613498266Sopenharmony_ci  ret = (*p->append)(p->arg, b, l);
104713498266Sopenharmony_ci  free(b);
104813498266Sopenharmony_ci  return ret == l? len: -1;
104913498266Sopenharmony_ci}
105013498266Sopenharmony_ci
105113498266Sopenharmony_ci
105213498266Sopenharmony_ciint
105313498266Sopenharmony_cicurl_formget_ccsid(struct curl_httppost *form, void *arg,
105413498266Sopenharmony_ci                   curl_formget_callback append, unsigned int ccsid)
105513498266Sopenharmony_ci{
105613498266Sopenharmony_ci  struct cfcdata lcfc;
105713498266Sopenharmony_ci
105813498266Sopenharmony_ci  lcfc.append = append;
105913498266Sopenharmony_ci  lcfc.arg = arg;
106013498266Sopenharmony_ci  lcfc.ccsid = ccsid;
106113498266Sopenharmony_ci  return curl_formget(form, (void *) &lcfc, Curl_formget_callback_ccsid);
106213498266Sopenharmony_ci}
106313498266Sopenharmony_ci
106413498266Sopenharmony_ci
106513498266Sopenharmony_ciCURLcode
106613498266Sopenharmony_cicurl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...)
106713498266Sopenharmony_ci{
106813498266Sopenharmony_ci  CURLcode result;
106913498266Sopenharmony_ci  va_list arg;
107013498266Sopenharmony_ci  char *s;
107113498266Sopenharmony_ci  char *cp = NULL;
107213498266Sopenharmony_ci  unsigned int ccsid;
107313498266Sopenharmony_ci  curl_off_t pfsize;
107413498266Sopenharmony_ci
107513498266Sopenharmony_ci  va_start(arg, tag);
107613498266Sopenharmony_ci
107713498266Sopenharmony_ci  switch(tag) {
107813498266Sopenharmony_ci
107913498266Sopenharmony_ci  /* BEGIN TRANSLATABLE STRING OPTIONS */
108013498266Sopenharmony_ci  /* Keep option symbols in alphanumeric order and retain the BEGIN/END
108113498266Sopenharmony_ci     armor comments. */
108213498266Sopenharmony_ci  case CURLOPT_ABSTRACT_UNIX_SOCKET:
108313498266Sopenharmony_ci  case CURLOPT_ACCEPT_ENCODING:
108413498266Sopenharmony_ci  case CURLOPT_ALTSVC:
108513498266Sopenharmony_ci  case CURLOPT_AWS_SIGV4:
108613498266Sopenharmony_ci  case CURLOPT_CAINFO:
108713498266Sopenharmony_ci  case CURLOPT_CAPATH:
108813498266Sopenharmony_ci  case CURLOPT_COOKIE:
108913498266Sopenharmony_ci  case CURLOPT_COOKIEFILE:
109013498266Sopenharmony_ci  case CURLOPT_COOKIEJAR:
109113498266Sopenharmony_ci  case CURLOPT_COOKIELIST:
109213498266Sopenharmony_ci  case CURLOPT_CRLFILE:
109313498266Sopenharmony_ci  case CURLOPT_CUSTOMREQUEST:
109413498266Sopenharmony_ci  case CURLOPT_DEFAULT_PROTOCOL:
109513498266Sopenharmony_ci  case CURLOPT_DNS_INTERFACE:
109613498266Sopenharmony_ci  case CURLOPT_DNS_LOCAL_IP4:
109713498266Sopenharmony_ci  case CURLOPT_DNS_LOCAL_IP6:
109813498266Sopenharmony_ci  case CURLOPT_DNS_SERVERS:
109913498266Sopenharmony_ci  case CURLOPT_DOH_URL:
110013498266Sopenharmony_ci  case CURLOPT_EGDSOCKET:
110113498266Sopenharmony_ci  case CURLOPT_FTPPORT:
110213498266Sopenharmony_ci  case CURLOPT_FTP_ACCOUNT:
110313498266Sopenharmony_ci  case CURLOPT_FTP_ALTERNATIVE_TO_USER:
110413498266Sopenharmony_ci  case CURLOPT_HAPROXY_CLIENT_IP:
110513498266Sopenharmony_ci  case CURLOPT_HSTS:
110613498266Sopenharmony_ci  case CURLOPT_INTERFACE:
110713498266Sopenharmony_ci  case CURLOPT_ISSUERCERT:
110813498266Sopenharmony_ci  case CURLOPT_KEYPASSWD:
110913498266Sopenharmony_ci  case CURLOPT_KRBLEVEL:
111013498266Sopenharmony_ci  case CURLOPT_LOGIN_OPTIONS:
111113498266Sopenharmony_ci  case CURLOPT_MAIL_AUTH:
111213498266Sopenharmony_ci  case CURLOPT_MAIL_FROM:
111313498266Sopenharmony_ci  case CURLOPT_NETRC_FILE:
111413498266Sopenharmony_ci  case CURLOPT_NOPROXY:
111513498266Sopenharmony_ci  case CURLOPT_PASSWORD:
111613498266Sopenharmony_ci  case CURLOPT_PINNEDPUBLICKEY:
111713498266Sopenharmony_ci  case CURLOPT_PRE_PROXY:
111813498266Sopenharmony_ci  case CURLOPT_PROTOCOLS_STR:
111913498266Sopenharmony_ci  case CURLOPT_PROXY:
112013498266Sopenharmony_ci  case CURLOPT_PROXYPASSWORD:
112113498266Sopenharmony_ci  case CURLOPT_PROXYUSERNAME:
112213498266Sopenharmony_ci  case CURLOPT_PROXYUSERPWD:
112313498266Sopenharmony_ci  case CURLOPT_PROXY_CAINFO:
112413498266Sopenharmony_ci  case CURLOPT_PROXY_CAPATH:
112513498266Sopenharmony_ci  case CURLOPT_PROXY_CRLFILE:
112613498266Sopenharmony_ci  case CURLOPT_PROXY_ISSUERCERT:
112713498266Sopenharmony_ci  case CURLOPT_PROXY_KEYPASSWD:
112813498266Sopenharmony_ci  case CURLOPT_PROXY_PINNEDPUBLICKEY:
112913498266Sopenharmony_ci  case CURLOPT_PROXY_SERVICE_NAME:
113013498266Sopenharmony_ci  case CURLOPT_PROXY_SSLCERT:
113113498266Sopenharmony_ci  case CURLOPT_PROXY_SSLCERTTYPE:
113213498266Sopenharmony_ci  case CURLOPT_PROXY_SSLKEY:
113313498266Sopenharmony_ci  case CURLOPT_PROXY_SSLKEYTYPE:
113413498266Sopenharmony_ci  case CURLOPT_PROXY_SSL_CIPHER_LIST:
113513498266Sopenharmony_ci  case CURLOPT_PROXY_TLS13_CIPHERS:
113613498266Sopenharmony_ci  case CURLOPT_PROXY_TLSAUTH_PASSWORD:
113713498266Sopenharmony_ci  case CURLOPT_PROXY_TLSAUTH_TYPE:
113813498266Sopenharmony_ci  case CURLOPT_PROXY_TLSAUTH_USERNAME:
113913498266Sopenharmony_ci  case CURLOPT_RANDOM_FILE:
114013498266Sopenharmony_ci  case CURLOPT_RANGE:
114113498266Sopenharmony_ci  case CURLOPT_REDIR_PROTOCOLS_STR:
114213498266Sopenharmony_ci  case CURLOPT_REFERER:
114313498266Sopenharmony_ci  case CURLOPT_REQUEST_TARGET:
114413498266Sopenharmony_ci  case CURLOPT_RTSP_SESSION_ID:
114513498266Sopenharmony_ci  case CURLOPT_RTSP_STREAM_URI:
114613498266Sopenharmony_ci  case CURLOPT_RTSP_TRANSPORT:
114713498266Sopenharmony_ci  case CURLOPT_SASL_AUTHZID:
114813498266Sopenharmony_ci  case CURLOPT_SERVICE_NAME:
114913498266Sopenharmony_ci  case CURLOPT_SOCKS5_GSSAPI_SERVICE:
115013498266Sopenharmony_ci  case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
115113498266Sopenharmony_ci  case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
115213498266Sopenharmony_ci  case CURLOPT_SSH_KNOWNHOSTS:
115313498266Sopenharmony_ci  case CURLOPT_SSH_PRIVATE_KEYFILE:
115413498266Sopenharmony_ci  case CURLOPT_SSH_PUBLIC_KEYFILE:
115513498266Sopenharmony_ci  case CURLOPT_SSLCERT:
115613498266Sopenharmony_ci  case CURLOPT_SSLCERTTYPE:
115713498266Sopenharmony_ci  case CURLOPT_SSLENGINE:
115813498266Sopenharmony_ci  case CURLOPT_SSLKEY:
115913498266Sopenharmony_ci  case CURLOPT_SSLKEYTYPE:
116013498266Sopenharmony_ci  case CURLOPT_SSL_CIPHER_LIST:
116113498266Sopenharmony_ci  case CURLOPT_SSL_EC_CURVES:
116213498266Sopenharmony_ci  case CURLOPT_TLS13_CIPHERS:
116313498266Sopenharmony_ci  case CURLOPT_TLSAUTH_PASSWORD:
116413498266Sopenharmony_ci  case CURLOPT_TLSAUTH_TYPE:
116513498266Sopenharmony_ci  case CURLOPT_TLSAUTH_USERNAME:
116613498266Sopenharmony_ci  case CURLOPT_UNIX_SOCKET_PATH:
116713498266Sopenharmony_ci  case CURLOPT_URL:
116813498266Sopenharmony_ci  case CURLOPT_USERAGENT:
116913498266Sopenharmony_ci  case CURLOPT_USERNAME:
117013498266Sopenharmony_ci  case CURLOPT_USERPWD:
117113498266Sopenharmony_ci  case CURLOPT_XOAUTH2_BEARER:
117213498266Sopenharmony_ci  /* END TRANSLATABLE STRING OPTIONS */
117313498266Sopenharmony_ci    s = va_arg(arg, char *);
117413498266Sopenharmony_ci    ccsid = va_arg(arg, unsigned int);
117513498266Sopenharmony_ci
117613498266Sopenharmony_ci    if(s) {
117713498266Sopenharmony_ci      s = dynconvert(ASCII_CCSID, s, -1, ccsid);
117813498266Sopenharmony_ci
117913498266Sopenharmony_ci      if(!s) {
118013498266Sopenharmony_ci        result = CURLE_OUT_OF_MEMORY;
118113498266Sopenharmony_ci        break;
118213498266Sopenharmony_ci      }
118313498266Sopenharmony_ci    }
118413498266Sopenharmony_ci
118513498266Sopenharmony_ci    result = curl_easy_setopt(easy, tag, s);
118613498266Sopenharmony_ci    free(s);
118713498266Sopenharmony_ci    break;
118813498266Sopenharmony_ci
118913498266Sopenharmony_ci  case CURLOPT_COPYPOSTFIELDS:
119013498266Sopenharmony_ci    /* Special case: byte count may have been given by CURLOPT_POSTFIELDSIZE
119113498266Sopenharmony_ci       prior to this call. In this case, convert the given byte count and
119213498266Sopenharmony_ci       replace the length according to the conversion result. */
119313498266Sopenharmony_ci    s = va_arg(arg, char *);
119413498266Sopenharmony_ci    ccsid = va_arg(arg, unsigned int);
119513498266Sopenharmony_ci
119613498266Sopenharmony_ci    pfsize = easy->set.postfieldsize;
119713498266Sopenharmony_ci
119813498266Sopenharmony_ci    if(!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) {
119913498266Sopenharmony_ci      result = curl_easy_setopt(easy, CURLOPT_COPYPOSTFIELDS, s);
120013498266Sopenharmony_ci      break;
120113498266Sopenharmony_ci    }
120213498266Sopenharmony_ci
120313498266Sopenharmony_ci    if(pfsize == -1) {
120413498266Sopenharmony_ci      /* Data is null-terminated. */
120513498266Sopenharmony_ci      s = dynconvert(ASCII_CCSID, s, -1, ccsid);
120613498266Sopenharmony_ci
120713498266Sopenharmony_ci      if(!s) {
120813498266Sopenharmony_ci        result = CURLE_OUT_OF_MEMORY;
120913498266Sopenharmony_ci        break;
121013498266Sopenharmony_ci        }
121113498266Sopenharmony_ci      }
121213498266Sopenharmony_ci    else {
121313498266Sopenharmony_ci      /* Data length specified. */
121413498266Sopenharmony_ci      size_t len;
121513498266Sopenharmony_ci
121613498266Sopenharmony_ci      if(pfsize < 0 || pfsize > SIZE_MAX) {
121713498266Sopenharmony_ci        result = CURLE_OUT_OF_MEMORY;
121813498266Sopenharmony_ci        break;
121913498266Sopenharmony_ci      }
122013498266Sopenharmony_ci
122113498266Sopenharmony_ci      len = pfsize;
122213498266Sopenharmony_ci      pfsize = len * MAX_CONV_EXPANSION;
122313498266Sopenharmony_ci
122413498266Sopenharmony_ci      if(pfsize > SIZE_MAX)
122513498266Sopenharmony_ci        pfsize = SIZE_MAX;
122613498266Sopenharmony_ci
122713498266Sopenharmony_ci      cp = malloc(pfsize);
122813498266Sopenharmony_ci
122913498266Sopenharmony_ci      if(!cp) {
123013498266Sopenharmony_ci        result = CURLE_OUT_OF_MEMORY;
123113498266Sopenharmony_ci        break;
123213498266Sopenharmony_ci      }
123313498266Sopenharmony_ci
123413498266Sopenharmony_ci      pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid);
123513498266Sopenharmony_ci
123613498266Sopenharmony_ci      if(pfsize < 0) {
123713498266Sopenharmony_ci        result = CURLE_OUT_OF_MEMORY;
123813498266Sopenharmony_ci        break;
123913498266Sopenharmony_ci      }
124013498266Sopenharmony_ci
124113498266Sopenharmony_ci      easy->set.postfieldsize = pfsize;         /* Replace data size. */
124213498266Sopenharmony_ci      s = cp;
124313498266Sopenharmony_ci    }
124413498266Sopenharmony_ci
124513498266Sopenharmony_ci    result = curl_easy_setopt(easy, CURLOPT_POSTFIELDS, s);
124613498266Sopenharmony_ci    easy->set.str[STRING_COPYPOSTFIELDS] = s;   /* Give to library. */
124713498266Sopenharmony_ci    break;
124813498266Sopenharmony_ci
124913498266Sopenharmony_ci  default:
125013498266Sopenharmony_ci    if(tag / 10000 == CURLOPTTYPE_BLOB) {
125113498266Sopenharmony_ci      struct curl_blob *bp = va_arg(arg, struct curl_blob *);
125213498266Sopenharmony_ci      struct curl_blob blob;
125313498266Sopenharmony_ci
125413498266Sopenharmony_ci      ccsid = va_arg(arg, unsigned int);
125513498266Sopenharmony_ci
125613498266Sopenharmony_ci      if(bp && bp->data && bp->len &&
125713498266Sopenharmony_ci         ccsid != NOCONV_CCSID && ccsid != ASCII_CCSID) {
125813498266Sopenharmony_ci        pfsize = (curl_off_t) bp->len * MAX_CONV_EXPANSION;
125913498266Sopenharmony_ci
126013498266Sopenharmony_ci        if(pfsize > SIZE_MAX)
126113498266Sopenharmony_ci          pfsize = SIZE_MAX;
126213498266Sopenharmony_ci
126313498266Sopenharmony_ci        cp = malloc(pfsize);
126413498266Sopenharmony_ci
126513498266Sopenharmony_ci        if(!cp) {
126613498266Sopenharmony_ci          result = CURLE_OUT_OF_MEMORY;
126713498266Sopenharmony_ci          break;
126813498266Sopenharmony_ci        }
126913498266Sopenharmony_ci
127013498266Sopenharmony_ci        pfsize = convert(cp, pfsize, ASCII_CCSID, bp->data, bp->len, ccsid);
127113498266Sopenharmony_ci
127213498266Sopenharmony_ci        if(pfsize < 0) {
127313498266Sopenharmony_ci          result = CURLE_OUT_OF_MEMORY;
127413498266Sopenharmony_ci          break;
127513498266Sopenharmony_ci        }
127613498266Sopenharmony_ci
127713498266Sopenharmony_ci        blob.data = cp;
127813498266Sopenharmony_ci        blob.len = pfsize;
127913498266Sopenharmony_ci        blob.flags = bp->flags | CURL_BLOB_COPY;
128013498266Sopenharmony_ci        bp = &blob;
128113498266Sopenharmony_ci      }
128213498266Sopenharmony_ci      result = curl_easy_setopt(easy, tag, &blob);
128313498266Sopenharmony_ci      break;
128413498266Sopenharmony_ci    }
128513498266Sopenharmony_ci    FALLTHROUGH();
128613498266Sopenharmony_ci  case CURLOPT_ERRORBUFFER:                     /* This is an output buffer. */
128713498266Sopenharmony_ci    result = Curl_vsetopt(easy, tag, arg);
128813498266Sopenharmony_ci    break;
128913498266Sopenharmony_ci  }
129013498266Sopenharmony_ci
129113498266Sopenharmony_ci  va_end(arg);
129213498266Sopenharmony_ci  free(cp);
129313498266Sopenharmony_ci  return result;
129413498266Sopenharmony_ci}
129513498266Sopenharmony_ci
129613498266Sopenharmony_ci
129713498266Sopenharmony_ci/* ILE/RPG helper functions. */
129813498266Sopenharmony_ci
129913498266Sopenharmony_cichar *
130013498266Sopenharmony_cicurl_form_long_value(long value)
130113498266Sopenharmony_ci{
130213498266Sopenharmony_ci  /* ILE/RPG cannot cast an integer to a pointer. This procedure does it. */
130313498266Sopenharmony_ci
130413498266Sopenharmony_ci  return (char *) value;
130513498266Sopenharmony_ci}
130613498266Sopenharmony_ci
130713498266Sopenharmony_ci
130813498266Sopenharmony_ciCURLcode
130913498266Sopenharmony_cicurl_easy_setopt_RPGnum_(CURL *easy, CURLoption tag, curl_off_t arg)
131013498266Sopenharmony_ci{
131113498266Sopenharmony_ci  /* ILE/RPG procedure overloading cannot discriminate between different
131213498266Sopenharmony_ci     size and/or signedness of format arguments. This provides a generic
131313498266Sopenharmony_ci     wrapper that adapts size to the given tag expectation.
131413498266Sopenharmony_ci     This procedure is not intended to be explicitly called from user code. */
131513498266Sopenharmony_ci  if(tag / 10000 != CURLOPTTYPE_OFF_T)
131613498266Sopenharmony_ci    return curl_easy_setopt(easy, tag, (long) arg);
131713498266Sopenharmony_ci  return curl_easy_setopt(easy, tag, arg);
131813498266Sopenharmony_ci}
131913498266Sopenharmony_ci
132013498266Sopenharmony_ci
132113498266Sopenharmony_ciCURLcode
132213498266Sopenharmony_cicurl_multi_setopt_RPGnum_(CURLM *multi, CURLMoption tag, curl_off_t arg)
132313498266Sopenharmony_ci{
132413498266Sopenharmony_ci  /* Likewise, for multi handle. */
132513498266Sopenharmony_ci  if(tag / 10000 != CURLOPTTYPE_OFF_T)
132613498266Sopenharmony_ci    return curl_multi_setopt(multi, tag, (long) arg);
132713498266Sopenharmony_ci  return curl_multi_setopt(multi, tag, arg);
132813498266Sopenharmony_ci}
132913498266Sopenharmony_ci
133013498266Sopenharmony_ci
133113498266Sopenharmony_cichar *
133213498266Sopenharmony_cicurl_pushheader_bynum_cssid(struct curl_pushheaders *h,
133313498266Sopenharmony_ci                            size_t num, unsigned int ccsid)
133413498266Sopenharmony_ci{
133513498266Sopenharmony_ci  char *d = (char *) NULL;
133613498266Sopenharmony_ci  char *s = curl_pushheader_bynum(h, num);
133713498266Sopenharmony_ci
133813498266Sopenharmony_ci  if(s)
133913498266Sopenharmony_ci    d = dynconvert(ccsid, s, -1, ASCII_CCSID);
134013498266Sopenharmony_ci
134113498266Sopenharmony_ci  return d;
134213498266Sopenharmony_ci}
134313498266Sopenharmony_ci
134413498266Sopenharmony_ci
134513498266Sopenharmony_cichar *
134613498266Sopenharmony_cicurl_pushheader_byname_ccsid(struct curl_pushheaders *h, const char *header,
134713498266Sopenharmony_ci                             unsigned int ccsidin, unsigned int ccsidout)
134813498266Sopenharmony_ci{
134913498266Sopenharmony_ci  char *d = (char *) NULL;
135013498266Sopenharmony_ci
135113498266Sopenharmony_ci  if(header) {
135213498266Sopenharmony_ci    header = dynconvert(ASCII_CCSID, header, -1, ccsidin);
135313498266Sopenharmony_ci
135413498266Sopenharmony_ci    if(header) {
135513498266Sopenharmony_ci      char *s = curl_pushheader_byname(h, header);
135613498266Sopenharmony_ci      free((char *) header);
135713498266Sopenharmony_ci
135813498266Sopenharmony_ci      if(s)
135913498266Sopenharmony_ci        d = dynconvert(ccsidout, s, -1, ASCII_CCSID);
136013498266Sopenharmony_ci    }
136113498266Sopenharmony_ci  }
136213498266Sopenharmony_ci
136313498266Sopenharmony_ci  return d;
136413498266Sopenharmony_ci}
136513498266Sopenharmony_ci
136613498266Sopenharmony_cistatic CURLcode
136713498266Sopenharmony_cimime_string_call(curl_mimepart *part, const char *string, unsigned int ccsid,
136813498266Sopenharmony_ci                 CURLcode (*mimefunc)(curl_mimepart *part, const char *string))
136913498266Sopenharmony_ci{
137013498266Sopenharmony_ci  char *s = (char *) NULL;
137113498266Sopenharmony_ci  CURLcode result;
137213498266Sopenharmony_ci
137313498266Sopenharmony_ci  if(!string)
137413498266Sopenharmony_ci    return mimefunc(part, string);
137513498266Sopenharmony_ci  s = dynconvert(ASCII_CCSID, string, -1, ccsid);
137613498266Sopenharmony_ci  if(!s)
137713498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
137813498266Sopenharmony_ci
137913498266Sopenharmony_ci  result = mimefunc(part, s);
138013498266Sopenharmony_ci  free(s);
138113498266Sopenharmony_ci  return result;
138213498266Sopenharmony_ci}
138313498266Sopenharmony_ci
138413498266Sopenharmony_ciCURLcode
138513498266Sopenharmony_cicurl_mime_name_ccsid(curl_mimepart *part, const char *name, unsigned int ccsid)
138613498266Sopenharmony_ci{
138713498266Sopenharmony_ci  return mime_string_call(part, name, ccsid, curl_mime_name);
138813498266Sopenharmony_ci}
138913498266Sopenharmony_ci
139013498266Sopenharmony_ciCURLcode
139113498266Sopenharmony_cicurl_mime_filename_ccsid(curl_mimepart *part,
139213498266Sopenharmony_ci                         const char *filename, unsigned int ccsid)
139313498266Sopenharmony_ci{
139413498266Sopenharmony_ci  return mime_string_call(part, filename, ccsid, curl_mime_filename);
139513498266Sopenharmony_ci}
139613498266Sopenharmony_ci
139713498266Sopenharmony_ciCURLcode
139813498266Sopenharmony_cicurl_mime_type_ccsid(curl_mimepart *part,
139913498266Sopenharmony_ci                     const char *mimetype, unsigned int ccsid)
140013498266Sopenharmony_ci{
140113498266Sopenharmony_ci  return mime_string_call(part, mimetype, ccsid, curl_mime_type);
140213498266Sopenharmony_ci}
140313498266Sopenharmony_ci
140413498266Sopenharmony_ciCURLcode
140513498266Sopenharmony_cicurl_mime_encoder_ccsid(curl_mimepart *part,
140613498266Sopenharmony_ci                       const char *encoding, unsigned int ccsid)
140713498266Sopenharmony_ci{
140813498266Sopenharmony_ci  return mime_string_call(part, encoding, ccsid, curl_mime_encoder);
140913498266Sopenharmony_ci}
141013498266Sopenharmony_ci
141113498266Sopenharmony_ciCURLcode
141213498266Sopenharmony_cicurl_mime_filedata_ccsid(curl_mimepart *part,
141313498266Sopenharmony_ci                         const char *filename, unsigned int ccsid)
141413498266Sopenharmony_ci{
141513498266Sopenharmony_ci  return mime_string_call(part, filename, ccsid, curl_mime_filedata);
141613498266Sopenharmony_ci}
141713498266Sopenharmony_ci
141813498266Sopenharmony_ciCURLcode
141913498266Sopenharmony_cicurl_mime_data_ccsid(curl_mimepart *part,
142013498266Sopenharmony_ci                     const char *data, size_t datasize, unsigned int ccsid)
142113498266Sopenharmony_ci{
142213498266Sopenharmony_ci  char *s = (char *) NULL;
142313498266Sopenharmony_ci  CURLcode result;
142413498266Sopenharmony_ci
142513498266Sopenharmony_ci  if(!data)
142613498266Sopenharmony_ci    return curl_mime_data(part, data, datasize);
142713498266Sopenharmony_ci  s = dynconvert(ASCII_CCSID, data, datasize, ccsid);
142813498266Sopenharmony_ci  if(!s)
142913498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
143013498266Sopenharmony_ci
143113498266Sopenharmony_ci  result = curl_mime_data(part, s, datasize);
143213498266Sopenharmony_ci  free(s);
143313498266Sopenharmony_ci  return result;
143413498266Sopenharmony_ci}
143513498266Sopenharmony_ci
143613498266Sopenharmony_ciCURLUcode
143713498266Sopenharmony_cicurl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part,
143813498266Sopenharmony_ci                   unsigned int flags, unsigned int ccsid)
143913498266Sopenharmony_ci{
144013498266Sopenharmony_ci  char *s = (char *)NULL;
144113498266Sopenharmony_ci  CURLUcode result;
144213498266Sopenharmony_ci
144313498266Sopenharmony_ci  if(!part)
144413498266Sopenharmony_ci    return CURLUE_BAD_PARTPOINTER;
144513498266Sopenharmony_ci
144613498266Sopenharmony_ci  *part = (char *)NULL;
144713498266Sopenharmony_ci  result = curl_url_get(handle, what, &s, flags);
144813498266Sopenharmony_ci  if(result == CURLUE_OK) {
144913498266Sopenharmony_ci    if(s) {
145013498266Sopenharmony_ci      *part = dynconvert(ccsid, s, -1, ASCII_CCSID);
145113498266Sopenharmony_ci      if(!*part)
145213498266Sopenharmony_ci        result = CURLUE_OUT_OF_MEMORY;
145313498266Sopenharmony_ci    }
145413498266Sopenharmony_ci  }
145513498266Sopenharmony_ci  if(s)
145613498266Sopenharmony_ci    free(s);
145713498266Sopenharmony_ci  return result;
145813498266Sopenharmony_ci}
145913498266Sopenharmony_ci
146013498266Sopenharmony_ciCURLUcode
146113498266Sopenharmony_cicurl_url_set_ccsid(CURLU *handle, CURLUPart what, const char *part,
146213498266Sopenharmony_ci                   unsigned int flags, unsigned int ccsid)
146313498266Sopenharmony_ci{
146413498266Sopenharmony_ci  char *s = (char *)NULL;
146513498266Sopenharmony_ci  CURLUcode result;
146613498266Sopenharmony_ci
146713498266Sopenharmony_ci  if(part) {
146813498266Sopenharmony_ci    s = dynconvert(ASCII_CCSID, part, -1, ccsid);
146913498266Sopenharmony_ci    if(!s)
147013498266Sopenharmony_ci      return CURLUE_OUT_OF_MEMORY;
147113498266Sopenharmony_ci  }
147213498266Sopenharmony_ci  result = curl_url_set(handle, what, s, flags);
147313498266Sopenharmony_ci  if(s)
147413498266Sopenharmony_ci    free(s);
147513498266Sopenharmony_ci  return result;
147613498266Sopenharmony_ci}
147713498266Sopenharmony_ci
147813498266Sopenharmony_ciconst struct curl_easyoption *
147913498266Sopenharmony_cicurl_easy_option_by_name_ccsid(const char *name, unsigned int ccsid)
148013498266Sopenharmony_ci{
148113498266Sopenharmony_ci  const struct curl_easyoption *option = NULL;
148213498266Sopenharmony_ci
148313498266Sopenharmony_ci  if(name) {
148413498266Sopenharmony_ci    char *s = dynconvert(ASCII_CCSID, name, -1, ccsid);
148513498266Sopenharmony_ci
148613498266Sopenharmony_ci    if(s) {
148713498266Sopenharmony_ci      option = curl_easy_option_by_name(s);
148813498266Sopenharmony_ci      free(s);
148913498266Sopenharmony_ci    }
149013498266Sopenharmony_ci  }
149113498266Sopenharmony_ci
149213498266Sopenharmony_ci  return option;
149313498266Sopenharmony_ci}
149413498266Sopenharmony_ci
149513498266Sopenharmony_ci/* Return option name in the given ccsid. */
149613498266Sopenharmony_ciconst char *
149713498266Sopenharmony_cicurl_easy_option_get_name_ccsid(const struct curl_easyoption *option,
149813498266Sopenharmony_ci                                unsigned int ccsid)
149913498266Sopenharmony_ci{
150013498266Sopenharmony_ci  char *name = NULL;
150113498266Sopenharmony_ci
150213498266Sopenharmony_ci  if(option && option->name)
150313498266Sopenharmony_ci    name = dynconvert(ccsid, option->name, -1, ASCII_CCSID);
150413498266Sopenharmony_ci
150513498266Sopenharmony_ci  return (const char *) name;
150613498266Sopenharmony_ci}
150713498266Sopenharmony_ci
150813498266Sopenharmony_ci/* Header API CCSID support. */
150913498266Sopenharmony_ciCURLHcode
151013498266Sopenharmony_cicurl_easy_header_ccsid(CURL *easy, const char *name, size_t index,
151113498266Sopenharmony_ci                       unsigned int origin, int request,
151213498266Sopenharmony_ci                       struct curl_header **hout, unsigned int ccsid)
151313498266Sopenharmony_ci{
151413498266Sopenharmony_ci  CURLHcode result = CURLHE_BAD_ARGUMENT;
151513498266Sopenharmony_ci
151613498266Sopenharmony_ci  if(name) {
151713498266Sopenharmony_ci    char *s = dynconvert(ASCII_CCSID, name, -1, ccsid);
151813498266Sopenharmony_ci
151913498266Sopenharmony_ci    result = CURLHE_OUT_OF_MEMORY;
152013498266Sopenharmony_ci    if(s) {
152113498266Sopenharmony_ci      result = curl_easy_header(easy, s, index, origin, request, hout);
152213498266Sopenharmony_ci      free(s);
152313498266Sopenharmony_ci    }
152413498266Sopenharmony_ci  }
152513498266Sopenharmony_ci
152613498266Sopenharmony_ci  return result;
152713498266Sopenharmony_ci}
1528