Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/packages/OS400/ccsidcurl.c
2066 views
1
/***************************************************************************
2
* _ _ ____ _
3
* Project ___| | | | _ \| |
4
* / __| | | | |_) | |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
7
*
8
* Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9
*
10
* This software is licensed as described in the file COPYING, which
11
* you should have received as part of this distribution. The terms
12
* are also available at https://curl.se/docs/copyright.html.
13
*
14
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
* copies of the Software, and permit persons to whom the Software is
16
* furnished to do so, under the terms of the COPYING file.
17
*
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
* KIND, either express or implied.
20
*
21
* SPDX-License-Identifier: curl
22
*
23
*
24
***************************************************************************/
25
26
/* CCSID API wrappers for OS/400. */
27
28
#include <iconv.h>
29
#include <string.h>
30
#include <stdlib.h>
31
#include <stddef.h>
32
#include <errno.h>
33
#include <stdarg.h>
34
35
#pragma enum(int)
36
37
#include "curl.h"
38
#include "mprintf.h"
39
#include "slist.h"
40
#include "urldata.h"
41
#include "url.h"
42
#include "setopt.h"
43
#include "getinfo.h"
44
#include "ccsidcurl.h"
45
46
#include "os400sys.h"
47
48
#ifndef SIZE_MAX
49
#define SIZE_MAX ((size_t) ~0) /* Is unsigned on OS/400. */
50
#endif
51
52
53
#define ASCII_CCSID 819 /* Use ISO-8859-1 as ASCII. */
54
#define NOCONV_CCSID 65535 /* No conversion. */
55
#define ICONV_ID_SIZE 32 /* Size of iconv_open() code identifier. */
56
#define ICONV_OPEN_ERROR(t) ((t).return_value == -1)
57
58
#define ALLOC_GRANULE 8 /* Alloc. granule for curl_formadd_ccsid(). */
59
60
61
static void
62
makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
63
{
64
/**
65
*** Convert a CCSID to the corresponding IBM iconv_open() character
66
*** code identifier.
67
*** This code is specific to the OS400 implementation of the iconv library.
68
*** CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
69
*** CCSID 0 is interpreted by the OS400 as the job's CCSID.
70
**/
71
72
ccsid &= 0xFFFF;
73
74
if(ccsid == NOCONV_CCSID)
75
ccsid = ASCII_CCSID;
76
77
memset(buf, 0, ICONV_ID_SIZE);
78
curl_msprintf(buf, "IBMCCSID%05u0000000", ccsid);
79
}
80
81
82
static iconv_t
83
iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin,
84
unsigned int cstr)
85
{
86
char fromcode[ICONV_ID_SIZE];
87
char tocode[ICONV_ID_SIZE];
88
89
/**
90
*** Like iconv_open(), but character codes are given as CCSIDs.
91
*** If `cstr' is non-zero, conversion is set up to stop whenever a
92
*** null character is encountered.
93
*** See iconv_open() IBM description in "National Language Support API".
94
**/
95
96
makeOS400IconvCode(fromcode, ccsidin);
97
makeOS400IconvCode(tocode, ccsidout);
98
memset(tocode + 13, 0, sizeof(tocode) - 13); /* Dest. code id format. */
99
100
if(cstr)
101
fromcode[18] = '1'; /* Set null-terminator flag. */
102
103
return iconv_open(tocode, fromcode);
104
}
105
106
107
static int
108
convert(char *d, size_t dlen, int dccsid,
109
const char *s, int slen, int sccsid)
110
{
111
int i;
112
iconv_t cd;
113
size_t lslen;
114
115
/**
116
*** Convert `sccsid'-coded `slen'-data bytes at `s' into `dccsid'-coded
117
*** data stored in the `dlen'-byte buffer at `d'.
118
*** If `slen' < 0, source string is null-terminated.
119
*** CCSID 65535 (no conversion) is replaced by the ASCII CCSID.
120
*** Return the converted destination byte count, or -1 if error.
121
**/
122
123
if(sccsid == 65535)
124
sccsid = ASCII_CCSID;
125
126
if(dccsid == 65535)
127
dccsid = ASCII_CCSID;
128
129
if(sccsid == dccsid) {
130
lslen = slen >= 0 ? slen : strlen(s) + 1;
131
i = lslen < dlen ? lslen : dlen;
132
133
if(s != d && i > 0)
134
memcpy(d, s, i);
135
136
return i;
137
}
138
139
if(slen < 0) {
140
lslen = 0;
141
cd = iconv_open_CCSID(dccsid, sccsid, 1);
142
}
143
else {
144
lslen = (size_t) slen;
145
cd = iconv_open_CCSID(dccsid, sccsid, 0);
146
}
147
148
if(ICONV_OPEN_ERROR(cd))
149
return -1;
150
151
i = dlen;
152
153
if((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0)
154
i = -1;
155
else
156
i -= dlen;
157
158
iconv_close(cd);
159
return i;
160
}
161
162
163
static char *dynconvert(int dccsid, const char *s, int slen, int sccsid)
164
{
165
char *d;
166
char *cp;
167
size_t dlen;
168
int l;
169
static const char nullbyte = 0;
170
171
/* Like convert, but the destination is allocated and returned. */
172
173
dlen = (size_t) (slen < 0 ? strlen(s) : slen) + 1;
174
dlen *= MAX_CONV_EXPANSION; /* Allow some expansion. */
175
d = malloc(dlen);
176
177
if(!d)
178
return (char *) NULL;
179
180
l = convert(d, dlen, dccsid, s, slen, sccsid);
181
182
if(l < 0) {
183
free(d);
184
return (char *) NULL;
185
}
186
187
if(slen < 0) {
188
/* Need to null-terminate even when source length is given.
189
Since destination code size is unknown, use a conversion to generate
190
terminator. */
191
192
int l2 = convert(d + l, dlen - l, dccsid, &nullbyte, -1, ASCII_CCSID);
193
194
if(l2 < 0) {
195
free(d);
196
return (char *) NULL;
197
}
198
199
l += l2;
200
}
201
202
if((size_t) l < dlen) {
203
cp = realloc(d, l); /* Shorten to minimum needed. */
204
205
if(cp)
206
d = cp;
207
}
208
209
return d;
210
}
211
212
213
static struct curl_slist *
214
slist_convert(int dccsid, struct curl_slist *from, int sccsid)
215
{
216
struct curl_slist *to = (struct curl_slist *) NULL;
217
218
for(; from; from = from->next) {
219
struct curl_slist *nl;
220
char *cp = dynconvert(dccsid, from->data, -1, sccsid);
221
222
if(!cp) {
223
curl_slist_free_all(to);
224
return (struct curl_slist *) NULL;
225
}
226
nl = Curl_slist_append_nodup(to, cp);
227
if(!nl) {
228
curl_slist_free_all(to);
229
free(cp);
230
return NULL;
231
}
232
to = nl;
233
}
234
return to;
235
}
236
237
238
static char *
239
keyed_string(localkey_t key, const char *ascii, unsigned int ccsid)
240
{
241
int i;
242
char *ebcdic;
243
244
if(!ascii)
245
return (char *) NULL;
246
247
i = MAX_CONV_EXPANSION * (strlen(ascii) + 1);
248
249
ebcdic = Curl_thread_buffer(key, i);
250
if(!ebcdic)
251
return ebcdic;
252
253
if(convert(ebcdic, i, ccsid, ascii, -1, ASCII_CCSID) < 0)
254
return (char *) NULL;
255
256
return ebcdic;
257
}
258
259
260
const char *
261
curl_to_ccsid(const char *s, unsigned int ccsid)
262
{
263
if(s)
264
s = dynconvert(ccsid, s, -1, ASCII_CCSID);
265
return s;
266
}
267
268
269
const char *
270
curl_from_ccsid(const char *s, unsigned int ccsid)
271
{
272
if(s)
273
s = dynconvert(ASCII_CCSID, s, -1, ccsid);
274
return s;
275
}
276
277
278
char *
279
curl_version_ccsid(unsigned int ccsid)
280
{
281
return keyed_string(LK_CURL_VERSION, curl_version(), ccsid);
282
}
283
284
285
char *
286
curl_easy_escape_ccsid(CURL *handle, const char *string, int length,
287
unsigned int sccsid, unsigned int dccsid)
288
{
289
char *s;
290
char *d;
291
292
if(!string) {
293
/* !checksrc! disable ERRNOVAR 1 */
294
errno = EINVAL;
295
return (char *) NULL;
296
}
297
298
s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid);
299
300
if(!s)
301
return (char *) NULL;
302
303
d = curl_easy_escape(handle, s, 0);
304
free(s);
305
306
if(!d)
307
return (char *) NULL;
308
309
s = dynconvert(dccsid, d, -1, ASCII_CCSID);
310
free(d);
311
return s;
312
}
313
314
315
char *
316
curl_easy_unescape_ccsid(CURL *handle, const char *string, int length,
317
int *outlength,
318
unsigned int sccsid, unsigned int dccsid)
319
{
320
char *s;
321
char *d;
322
323
if(!string) {
324
/* !checksrc! disable ERRNOVAR 1 */
325
errno = EINVAL;
326
return (char *) NULL;
327
}
328
329
s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid);
330
331
if(!s)
332
return (char *) NULL;
333
334
d = curl_easy_unescape(handle, s, 0, outlength);
335
free(s);
336
337
if(!d)
338
return (char *) NULL;
339
340
s = dynconvert(dccsid, d, -1, ASCII_CCSID);
341
free(d);
342
343
if(s && outlength)
344
*outlength = strlen(s);
345
346
return s;
347
}
348
349
350
struct curl_slist *
351
curl_slist_append_ccsid(struct curl_slist *list,
352
const char *data, unsigned int ccsid)
353
{
354
char *s;
355
356
s = (char *) NULL;
357
358
if(!data)
359
return curl_slist_append(list, data);
360
361
s = dynconvert(ASCII_CCSID, data, -1, ccsid);
362
363
if(!s)
364
return (struct curl_slist *) NULL;
365
366
list = curl_slist_append(list, s);
367
free(s);
368
return list;
369
}
370
371
372
time_t
373
curl_getdate_ccsid(const char *p, const time_t *unused, unsigned int ccsid)
374
{
375
char *s;
376
time_t t;
377
378
if(!p)
379
return curl_getdate(p, unused);
380
381
s = dynconvert(ASCII_CCSID, p, -1, ccsid);
382
383
if(!s)
384
return (time_t) -1;
385
386
t = curl_getdate(s, unused);
387
free(s);
388
return t;
389
}
390
391
392
static int
393
convert_version_info_string(const char **stringp,
394
char **bufp, int *left, unsigned int ccsid)
395
{
396
/* Helper for curl_version_info_ccsid(): convert a string if defined.
397
Result is stored in the `*left'-byte buffer at `*bufp'.
398
`*bufp' and `*left' are updated accordingly.
399
Return 0 if ok, else -1. */
400
401
if(*stringp) {
402
int l = convert(*bufp, *left, ccsid, *stringp, -1, ASCII_CCSID);
403
404
if(l <= 0)
405
return -1;
406
407
*stringp = *bufp;
408
*bufp += l;
409
*left -= l;
410
}
411
412
return 0;
413
}
414
415
416
curl_version_info_data *
417
curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
418
{
419
curl_version_info_data *p;
420
char *cp;
421
int n;
422
int nproto;
423
curl_version_info_data *id;
424
int i;
425
const char **cpp;
426
static const size_t charfields[] = {
427
offsetof(curl_version_info_data, version),
428
offsetof(curl_version_info_data, host),
429
offsetof(curl_version_info_data, ssl_version),
430
offsetof(curl_version_info_data, libz_version),
431
offsetof(curl_version_info_data, ares),
432
offsetof(curl_version_info_data, libidn),
433
offsetof(curl_version_info_data, libssh_version),
434
offsetof(curl_version_info_data, brotli_version),
435
offsetof(curl_version_info_data, nghttp2_version),
436
offsetof(curl_version_info_data, quic_version),
437
offsetof(curl_version_info_data, cainfo),
438
offsetof(curl_version_info_data, capath),
439
offsetof(curl_version_info_data, zstd_version),
440
offsetof(curl_version_info_data, hyper_version),
441
offsetof(curl_version_info_data, gsasl_version),
442
offsetof(curl_version_info_data, feature_names),
443
offsetof(curl_version_info_data, rtmp_version)
444
};
445
446
/* The assertion below is possible, because although the second operand
447
is an enum member, the first is a #define. In that case, the OS/400 C
448
compiler seems to compare string values after substitution. */
449
450
#if CURLVERSION_NOW != CURLVERSION_ELEVENTH
451
#error curl_version_info_data structure has changed: upgrade this procedure.
452
#endif
453
454
/* If caller has been compiled with a newer version, error. */
455
456
if(stamp > CURLVERSION_NOW)
457
return (curl_version_info_data *) NULL;
458
459
p = curl_version_info(stamp);
460
461
if(!p)
462
return p;
463
464
/* Measure thread space needed. */
465
466
n = 0;
467
nproto = 0;
468
469
if(p->protocols) {
470
while(p->protocols[nproto])
471
n += strlen(p->protocols[nproto++]);
472
473
n += nproto++;
474
}
475
476
for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) {
477
cpp = (const char **) ((char *) p + charfields[i]);
478
if(*cpp)
479
n += strlen(*cpp) + 1;
480
}
481
482
/* Allocate thread space. */
483
484
n *= MAX_CONV_EXPANSION;
485
486
if(nproto)
487
n += nproto * sizeof(const char *);
488
489
cp = Curl_thread_buffer(LK_VERSION_INFO_DATA, n);
490
id = (curl_version_info_data *) Curl_thread_buffer(LK_VERSION_INFO,
491
sizeof(*id));
492
493
if(!id || !cp)
494
return (curl_version_info_data *) NULL;
495
496
/* Copy data and convert strings. */
497
498
memcpy((char *) id, (char *) p, sizeof(*p));
499
500
if(id->protocols) {
501
i = nproto * sizeof(id->protocols[0]);
502
503
id->protocols = (const char * const *) cp;
504
memcpy(cp, (char *) p->protocols, i);
505
cp += i;
506
n -= i;
507
508
for(i = 0; id->protocols[i]; i++)
509
if(convert_version_info_string(((const char * *) id->protocols) + i,
510
&cp, &n, ccsid))
511
return (curl_version_info_data *) NULL;
512
}
513
514
for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) {
515
cpp = (const char **) ((char *) p + charfields[i]);
516
if(*cpp && convert_version_info_string(cpp, &cp, &n, ccsid))
517
return (curl_version_info_data *) NULL;
518
}
519
520
return id;
521
}
522
523
524
const char *
525
curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid)
526
{
527
return keyed_string(LK_EASY_STRERROR, curl_easy_strerror(error), ccsid);
528
}
529
530
531
const char *
532
curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid)
533
{
534
return keyed_string(LK_SHARE_STRERROR, curl_share_strerror(error), ccsid);
535
}
536
537
538
const char *
539
curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid)
540
{
541
return keyed_string(LK_MULTI_STRERROR, curl_multi_strerror(error), ccsid);
542
}
543
544
545
const char *
546
curl_url_strerror_ccsid(CURLUcode error, unsigned int ccsid)
547
{
548
return keyed_string(LK_URL_STRERROR, curl_url_strerror(error), ccsid);
549
}
550
551
552
void
553
curl_certinfo_free_all(struct curl_certinfo *info)
554
{
555
/* Free all memory used by certificate info. */
556
if(info) {
557
if(info->certinfo) {
558
int i;
559
560
for(i = 0; i < info->num_of_certs; i++)
561
curl_slist_free_all(info->certinfo[i]);
562
free((char *) info->certinfo);
563
}
564
free((char *) info);
565
}
566
}
567
568
569
CURLcode
570
curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...)
571
{
572
va_list arg;
573
void *paramp;
574
CURLcode ret;
575
struct Curl_easy *data;
576
577
/* WARNING: unlike curl_easy_getinfo(), the strings returned by this
578
procedure have to be free'ed. */
579
580
data = (struct Curl_easy *) curl;
581
va_start(arg, info);
582
paramp = va_arg(arg, void *);
583
ret = Curl_getinfo(data, info, paramp);
584
585
if(ret == CURLE_OK) {
586
unsigned int ccsid;
587
char **cpp;
588
struct curl_slist **slp;
589
struct curl_certinfo *cipf;
590
struct curl_certinfo *cipt;
591
592
switch((int) info & CURLINFO_TYPEMASK) {
593
594
case CURLINFO_STRING:
595
ccsid = va_arg(arg, unsigned int);
596
cpp = (char * *) paramp;
597
598
if(*cpp) {
599
*cpp = dynconvert(ccsid, *cpp, -1, ASCII_CCSID);
600
601
if(!*cpp)
602
ret = CURLE_OUT_OF_MEMORY;
603
}
604
605
break;
606
607
case CURLINFO_SLIST:
608
ccsid = va_arg(arg, unsigned int);
609
switch(info) {
610
case CURLINFO_CERTINFO:
611
cipf = *(struct curl_certinfo * *) paramp;
612
if(cipf) {
613
cipt = (struct curl_certinfo *) malloc(sizeof(*cipt));
614
if(!cipt)
615
ret = CURLE_OUT_OF_MEMORY;
616
else {
617
cipt->certinfo = (struct curl_slist **)
618
calloc(cipf->num_of_certs +
619
1, sizeof(struct curl_slist *));
620
if(!cipt->certinfo)
621
ret = CURLE_OUT_OF_MEMORY;
622
else {
623
int i;
624
625
cipt->num_of_certs = cipf->num_of_certs;
626
for(i = 0; i < cipf->num_of_certs; i++)
627
if(cipf->certinfo[i])
628
if(!(cipt->certinfo[i] = slist_convert(ccsid,
629
cipf->certinfo[i],
630
ASCII_CCSID))) {
631
ret = CURLE_OUT_OF_MEMORY;
632
break;
633
}
634
}
635
}
636
637
if(ret != CURLE_OK) {
638
curl_certinfo_free_all(cipt);
639
cipt = (struct curl_certinfo *) NULL;
640
}
641
642
*(struct curl_certinfo * *) paramp = cipt;
643
}
644
645
break;
646
647
case CURLINFO_TLS_SESSION:
648
case CURLINFO_TLS_SSL_PTR:
649
case CURLINFO_SOCKET:
650
break;
651
652
default:
653
slp = (struct curl_slist **) paramp;
654
if(*slp) {
655
*slp = slist_convert(ccsid, *slp, ASCII_CCSID);
656
if(!*slp)
657
ret = CURLE_OUT_OF_MEMORY;
658
}
659
break;
660
}
661
}
662
}
663
664
va_end(arg);
665
return ret;
666
}
667
668
669
static int
670
Curl_is_formadd_string(CURLformoption option)
671
{
672
switch(option) {
673
674
case CURLFORM_FILENAME:
675
case CURLFORM_CONTENTTYPE:
676
case CURLFORM_BUFFER:
677
case CURLFORM_FILE:
678
case CURLFORM_FILECONTENT:
679
case CURLFORM_COPYCONTENTS:
680
case CURLFORM_COPYNAME:
681
return 1;
682
}
683
684
return 0;
685
}
686
687
688
static void
689
Curl_formadd_release_local(struct curl_forms *forms, int nargs, int skip)
690
{
691
while(nargs--)
692
if(nargs != skip)
693
if(Curl_is_formadd_string(forms[nargs].option))
694
if(forms[nargs].value)
695
free((char *) forms[nargs].value);
696
697
free((char *) forms);
698
}
699
700
701
static int
702
Curl_formadd_convert(struct curl_forms *forms,
703
int formx, int lengthx, unsigned int ccsid)
704
{
705
int l;
706
char *cp;
707
char *cp2;
708
709
if(formx < 0 || !forms[formx].value)
710
return 0;
711
712
if(lengthx >= 0)
713
l = (int) forms[lengthx].value;
714
else
715
l = strlen(forms[formx].value) + 1;
716
717
cp = malloc(MAX_CONV_EXPANSION * l);
718
719
if(!cp)
720
return -1;
721
722
l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID,
723
forms[formx].value, l, ccsid);
724
725
if(l < 0) {
726
free(cp);
727
return -1;
728
}
729
730
cp2 = realloc(cp, l); /* Shorten buffer to the string size. */
731
732
if(cp2)
733
cp = cp2;
734
735
forms[formx].value = cp;
736
737
if(lengthx >= 0)
738
forms[lengthx].value = (char *) l; /* Update length after conversion. */
739
740
return l;
741
}
742
743
744
CURLFORMcode
745
curl_formadd_ccsid(struct curl_httppost **httppost,
746
struct curl_httppost **last_post, ...)
747
{
748
va_list arg;
749
CURLformoption option;
750
CURLFORMcode result;
751
struct curl_forms *forms;
752
struct curl_forms *lforms;
753
struct curl_forms *tforms;
754
unsigned int lformlen;
755
const char *value;
756
unsigned int ccsid;
757
int nargs;
758
int namex;
759
int namelengthx;
760
int contentx;
761
int lengthx;
762
unsigned int contentccsid;
763
unsigned int nameccsid;
764
765
/* A single curl_formadd() call cannot be split in several calls to deal
766
with all parameters: the original parameters are thus copied to a local
767
curl_forms array and converted to ASCII when needed.
768
CURLFORM_PTRNAME is processed as if it were CURLFORM_COPYNAME.
769
CURLFORM_COPYNAME and CURLFORM_NAMELENGTH occurrence order in
770
parameters is not defined; for this reason, the actual conversion is
771
delayed to the end of parameter processing. The same applies to
772
CURLFORM_COPYCONTENTS/CURLFORM_CONTENTSLENGTH, but these may appear
773
several times in the parameter list; the problem resides here in knowing
774
which CURLFORM_CONTENTSLENGTH applies to which CURLFORM_COPYCONTENTS and
775
when we can be sure to have both info for conversion: end of parameter
776
list is such a point, but CURLFORM_CONTENTTYPE is also used here as a
777
natural separator between content data definitions; this seems to be
778
in accordance with FormAdd() behavior. */
779
780
/* Allocate the local curl_forms array. */
781
782
lformlen = ALLOC_GRANULE;
783
lforms = malloc(lformlen * sizeof(*lforms));
784
785
if(!lforms)
786
return CURL_FORMADD_MEMORY;
787
788
/* Process the arguments, copying them into local array, latching conversion
789
indexes and converting when needed. */
790
791
result = CURL_FORMADD_OK;
792
nargs = 0;
793
contentx = -1;
794
lengthx = -1;
795
namex = -1;
796
namelengthx = -1;
797
forms = (struct curl_forms *) NULL;
798
va_start(arg, last_post);
799
800
for(;;) {
801
/* Make sure there is still room for an item in local array. */
802
803
if(nargs >= lformlen) {
804
lformlen += ALLOC_GRANULE;
805
tforms = realloc(lforms, lformlen * sizeof(*lforms));
806
807
if(!tforms) {
808
result = CURL_FORMADD_MEMORY;
809
break;
810
}
811
812
lforms = tforms;
813
}
814
815
/* Get next option. */
816
817
if(forms) {
818
/* Get option from array. */
819
820
option = forms->option;
821
value = forms->value;
822
forms++;
823
}
824
else {
825
/* Get option from arguments. */
826
827
option = va_arg(arg, CURLformoption);
828
829
if(option == CURLFORM_END)
830
break;
831
}
832
833
/* Dispatch by option. */
834
835
switch(option) {
836
837
case CURLFORM_END:
838
forms = (struct curl_forms *) NULL; /* Leave array mode. */
839
continue;
840
841
case CURLFORM_ARRAY:
842
if(!forms) {
843
forms = va_arg(arg, struct curl_forms *);
844
continue;
845
}
846
847
result = CURL_FORMADD_ILLEGAL_ARRAY;
848
break;
849
850
case CURLFORM_COPYNAME:
851
option = CURLFORM_PTRNAME; /* Static for now. */
852
853
case CURLFORM_PTRNAME:
854
if(namex >= 0)
855
result = CURL_FORMADD_OPTION_TWICE;
856
857
namex = nargs;
858
859
if(!forms) {
860
value = va_arg(arg, char *);
861
nameccsid = (unsigned int) va_arg(arg, long);
862
}
863
else {
864
nameccsid = (unsigned int) forms->value;
865
forms++;
866
}
867
868
break;
869
870
case CURLFORM_COPYCONTENTS:
871
if(contentx >= 0)
872
result = CURL_FORMADD_OPTION_TWICE;
873
874
contentx = nargs;
875
876
if(!forms) {
877
value = va_arg(arg, char *);
878
contentccsid = (unsigned int) va_arg(arg, long);
879
}
880
else {
881
contentccsid = (unsigned int) forms->value;
882
forms++;
883
}
884
885
break;
886
887
case CURLFORM_PTRCONTENTS:
888
case CURLFORM_BUFFERPTR:
889
if(!forms)
890
value = va_arg(arg, char *); /* No conversion. */
891
892
break;
893
894
case CURLFORM_CONTENTSLENGTH:
895
lengthx = nargs;
896
897
if(!forms)
898
value = (char *) va_arg(arg, long);
899
900
break;
901
902
case CURLFORM_CONTENTLEN:
903
lengthx = nargs;
904
905
if(!forms)
906
value = (char *) va_arg(arg, curl_off_t);
907
908
break;
909
910
case CURLFORM_NAMELENGTH:
911
namelengthx = nargs;
912
913
if(!forms)
914
value = (char *) va_arg(arg, long);
915
916
break;
917
918
case CURLFORM_BUFFERLENGTH:
919
if(!forms)
920
value = (char *) va_arg(arg, long);
921
922
break;
923
924
case CURLFORM_CONTENTHEADER:
925
if(!forms)
926
value = (char *) va_arg(arg, struct curl_slist *);
927
928
break;
929
930
case CURLFORM_STREAM:
931
if(!forms)
932
value = (char *) va_arg(arg, void *);
933
934
break;
935
936
case CURLFORM_CONTENTTYPE:
937
/* If a previous content has been encountered, convert it now. */
938
939
if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) {
940
result = CURL_FORMADD_MEMORY;
941
break;
942
}
943
944
contentx = -1;
945
lengthx = -1;
946
/* Fall into default. */
947
948
default:
949
/* Must be a convertible string. */
950
951
if(!Curl_is_formadd_string(option)) {
952
result = CURL_FORMADD_UNKNOWN_OPTION;
953
break;
954
}
955
956
if(!forms) {
957
value = va_arg(arg, char *);
958
ccsid = (unsigned int) va_arg(arg, long);
959
}
960
else {
961
ccsid = (unsigned int) forms->value;
962
forms++;
963
}
964
965
/* Do the conversion. */
966
967
lforms[nargs].value = value;
968
969
if(Curl_formadd_convert(lforms, nargs, -1, ccsid) < 0) {
970
result = CURL_FORMADD_MEMORY;
971
break;
972
}
973
974
value = lforms[nargs].value;
975
}
976
977
if(result != CURL_FORMADD_OK)
978
break;
979
980
lforms[nargs].value = value;
981
lforms[nargs++].option = option;
982
}
983
984
va_end(arg);
985
986
/* Convert the name and the last content, now that we know their lengths. */
987
988
if(result == CURL_FORMADD_OK && namex >= 0) {
989
if(Curl_formadd_convert(lforms, namex, namelengthx, nameccsid) < 0)
990
result = CURL_FORMADD_MEMORY;
991
else
992
lforms[namex].option = CURLFORM_COPYNAME; /* Force copy. */
993
}
994
995
if(result == CURL_FORMADD_OK) {
996
if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0)
997
result = CURL_FORMADD_MEMORY;
998
else
999
contentx = -1;
1000
}
1001
1002
/* Do the formadd with our converted parameters. */
1003
1004
if(result == CURL_FORMADD_OK) {
1005
lforms[nargs].option = CURLFORM_END;
1006
result = curl_formadd(httppost, last_post,
1007
CURLFORM_ARRAY, lforms, CURLFORM_END);
1008
}
1009
1010
/* Terminate. */
1011
1012
Curl_formadd_release_local(lforms, nargs, contentx);
1013
return result;
1014
}
1015
1016
1017
struct cfcdata {
1018
curl_formget_callback append;
1019
void * arg;
1020
unsigned int ccsid;
1021
};
1022
1023
1024
static size_t
1025
Curl_formget_callback_ccsid(void *arg, const char *buf, size_t len)
1026
{
1027
struct cfcdata *p;
1028
char *b;
1029
int l;
1030
size_t ret;
1031
1032
p = (struct cfcdata *) arg;
1033
1034
if((long) len <= 0)
1035
return (*p->append)(p->arg, buf, len);
1036
1037
b = malloc(MAX_CONV_EXPANSION * len);
1038
1039
if(!b)
1040
return (size_t) -1;
1041
1042
l = convert(b, MAX_CONV_EXPANSION * len, p->ccsid, buf, len, ASCII_CCSID);
1043
1044
if(l < 0) {
1045
free(b);
1046
return (size_t) -1;
1047
}
1048
1049
ret = (*p->append)(p->arg, b, l);
1050
free(b);
1051
return ret == l ? len : -1;
1052
}
1053
1054
1055
int
1056
curl_formget_ccsid(struct curl_httppost *form, void *arg,
1057
curl_formget_callback append, unsigned int ccsid)
1058
{
1059
struct cfcdata lcfc;
1060
1061
lcfc.append = append;
1062
lcfc.arg = arg;
1063
lcfc.ccsid = ccsid;
1064
return curl_formget(form, (void *) &lcfc, Curl_formget_callback_ccsid);
1065
}
1066
1067
1068
CURLcode
1069
curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...)
1070
{
1071
CURLcode result;
1072
va_list arg;
1073
char *s;
1074
char *cp = NULL;
1075
unsigned int ccsid;
1076
curl_off_t pfsize;
1077
struct Curl_easy *data = easy;
1078
1079
va_start(arg, tag);
1080
1081
switch(tag) {
1082
1083
/* BEGIN TRANSLATABLE STRING OPTIONS */
1084
/* Keep option symbols in alphanumeric order and retain the BEGIN/END
1085
armor comments. */
1086
case CURLOPT_ABSTRACT_UNIX_SOCKET:
1087
case CURLOPT_ACCEPT_ENCODING:
1088
case CURLOPT_ALTSVC:
1089
case CURLOPT_AWS_SIGV4:
1090
case CURLOPT_CAINFO:
1091
case CURLOPT_CAPATH:
1092
case CURLOPT_COOKIE:
1093
case CURLOPT_COOKIEFILE:
1094
case CURLOPT_COOKIEJAR:
1095
case CURLOPT_COOKIELIST:
1096
case CURLOPT_CRLFILE:
1097
case CURLOPT_CUSTOMREQUEST:
1098
case CURLOPT_DEFAULT_PROTOCOL:
1099
case CURLOPT_DNS_INTERFACE:
1100
case CURLOPT_DNS_LOCAL_IP4:
1101
case CURLOPT_DNS_LOCAL_IP6:
1102
case CURLOPT_DNS_SERVERS:
1103
case CURLOPT_DOH_URL:
1104
case CURLOPT_ECH:
1105
case CURLOPT_EGDSOCKET:
1106
case CURLOPT_FTPPORT:
1107
case CURLOPT_FTP_ACCOUNT:
1108
case CURLOPT_FTP_ALTERNATIVE_TO_USER:
1109
case CURLOPT_HAPROXY_CLIENT_IP:
1110
case CURLOPT_HSTS:
1111
case CURLOPT_INTERFACE:
1112
case CURLOPT_ISSUERCERT:
1113
case CURLOPT_KEYPASSWD:
1114
case CURLOPT_KRBLEVEL:
1115
case CURLOPT_LOGIN_OPTIONS:
1116
case CURLOPT_MAIL_AUTH:
1117
case CURLOPT_MAIL_FROM:
1118
case CURLOPT_NETRC_FILE:
1119
case CURLOPT_NOPROXY:
1120
case CURLOPT_PASSWORD:
1121
case CURLOPT_PINNEDPUBLICKEY:
1122
case CURLOPT_PRE_PROXY:
1123
case CURLOPT_PROTOCOLS_STR:
1124
case CURLOPT_PROXY:
1125
case CURLOPT_PROXYPASSWORD:
1126
case CURLOPT_PROXYUSERNAME:
1127
case CURLOPT_PROXYUSERPWD:
1128
case CURLOPT_PROXY_CAINFO:
1129
case CURLOPT_PROXY_CAPATH:
1130
case CURLOPT_PROXY_CRLFILE:
1131
case CURLOPT_PROXY_ISSUERCERT:
1132
case CURLOPT_PROXY_KEYPASSWD:
1133
case CURLOPT_PROXY_PINNEDPUBLICKEY:
1134
case CURLOPT_PROXY_SERVICE_NAME:
1135
case CURLOPT_PROXY_SSLCERT:
1136
case CURLOPT_PROXY_SSLCERTTYPE:
1137
case CURLOPT_PROXY_SSLKEY:
1138
case CURLOPT_PROXY_SSLKEYTYPE:
1139
case CURLOPT_PROXY_SSL_CIPHER_LIST:
1140
case CURLOPT_PROXY_TLS13_CIPHERS:
1141
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
1142
case CURLOPT_PROXY_TLSAUTH_TYPE:
1143
case CURLOPT_PROXY_TLSAUTH_USERNAME:
1144
case CURLOPT_RANDOM_FILE:
1145
case CURLOPT_RANGE:
1146
case CURLOPT_REDIR_PROTOCOLS_STR:
1147
case CURLOPT_REFERER:
1148
case CURLOPT_REQUEST_TARGET:
1149
case CURLOPT_RTSP_SESSION_ID:
1150
case CURLOPT_RTSP_STREAM_URI:
1151
case CURLOPT_RTSP_TRANSPORT:
1152
case CURLOPT_SASL_AUTHZID:
1153
case CURLOPT_SERVICE_NAME:
1154
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
1155
case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
1156
case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
1157
case CURLOPT_SSH_KNOWNHOSTS:
1158
case CURLOPT_SSH_PRIVATE_KEYFILE:
1159
case CURLOPT_SSH_PUBLIC_KEYFILE:
1160
case CURLOPT_SSLCERT:
1161
case CURLOPT_SSLCERTTYPE:
1162
case CURLOPT_SSLENGINE:
1163
case CURLOPT_SSLKEY:
1164
case CURLOPT_SSLKEYTYPE:
1165
case CURLOPT_SSL_CIPHER_LIST:
1166
case CURLOPT_SSL_EC_CURVES:
1167
case CURLOPT_SSL_SIGNATURE_ALGORITHMS:
1168
case CURLOPT_TLS13_CIPHERS:
1169
case CURLOPT_TLSAUTH_PASSWORD:
1170
case CURLOPT_TLSAUTH_TYPE:
1171
case CURLOPT_TLSAUTH_USERNAME:
1172
case CURLOPT_UNIX_SOCKET_PATH:
1173
case CURLOPT_URL:
1174
case CURLOPT_USERAGENT:
1175
case CURLOPT_USERNAME:
1176
case CURLOPT_USERPWD:
1177
case CURLOPT_XOAUTH2_BEARER:
1178
/* END TRANSLATABLE STRING OPTIONS */
1179
s = va_arg(arg, char *);
1180
ccsid = va_arg(arg, unsigned int);
1181
1182
if(s) {
1183
s = dynconvert(ASCII_CCSID, s, -1, ccsid);
1184
1185
if(!s) {
1186
result = CURLE_OUT_OF_MEMORY;
1187
break;
1188
}
1189
}
1190
1191
result = curl_easy_setopt(easy, tag, s);
1192
free(s);
1193
break;
1194
1195
case CURLOPT_COPYPOSTFIELDS:
1196
/* Special case: byte count may have been given by CURLOPT_POSTFIELDSIZE
1197
prior to this call. In this case, convert the given byte count and
1198
replace the length according to the conversion result. */
1199
s = va_arg(arg, char *);
1200
ccsid = va_arg(arg, unsigned int);
1201
1202
pfsize = data->set.postfieldsize;
1203
1204
if(!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) {
1205
result = curl_easy_setopt(easy, CURLOPT_COPYPOSTFIELDS, s);
1206
break;
1207
}
1208
1209
if(pfsize == -1) {
1210
/* Data is null-terminated. */
1211
s = dynconvert(ASCII_CCSID, s, -1, ccsid);
1212
1213
if(!s) {
1214
result = CURLE_OUT_OF_MEMORY;
1215
break;
1216
}
1217
}
1218
else {
1219
/* Data length specified. */
1220
size_t len;
1221
1222
if(pfsize < 0 || pfsize > SIZE_MAX) {
1223
result = CURLE_OUT_OF_MEMORY;
1224
break;
1225
}
1226
1227
len = pfsize;
1228
pfsize = len * MAX_CONV_EXPANSION;
1229
1230
if(pfsize > SIZE_MAX)
1231
pfsize = SIZE_MAX;
1232
1233
cp = malloc(pfsize);
1234
1235
if(!cp) {
1236
result = CURLE_OUT_OF_MEMORY;
1237
break;
1238
}
1239
1240
pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid);
1241
1242
if(pfsize < 0) {
1243
result = CURLE_OUT_OF_MEMORY;
1244
break;
1245
}
1246
1247
data->set.postfieldsize = pfsize; /* Replace data size. */
1248
s = cp;
1249
}
1250
1251
result = curl_easy_setopt(easy, CURLOPT_POSTFIELDS, s);
1252
data->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */
1253
break;
1254
1255
default:
1256
if(tag / 10000 == CURLOPTTYPE_BLOB) {
1257
struct curl_blob *bp = va_arg(arg, struct curl_blob *);
1258
struct curl_blob blob;
1259
1260
ccsid = va_arg(arg, unsigned int);
1261
1262
if(bp && bp->data && bp->len &&
1263
ccsid != NOCONV_CCSID && ccsid != ASCII_CCSID) {
1264
pfsize = (curl_off_t) bp->len * MAX_CONV_EXPANSION;
1265
1266
if(pfsize > SIZE_MAX)
1267
pfsize = SIZE_MAX;
1268
1269
cp = malloc(pfsize);
1270
1271
if(!cp) {
1272
result = CURLE_OUT_OF_MEMORY;
1273
break;
1274
}
1275
1276
pfsize = convert(cp, pfsize, ASCII_CCSID, bp->data, bp->len, ccsid);
1277
1278
if(pfsize < 0) {
1279
result = CURLE_OUT_OF_MEMORY;
1280
break;
1281
}
1282
1283
blob.data = cp;
1284
blob.len = pfsize;
1285
blob.flags = bp->flags | CURL_BLOB_COPY;
1286
bp = &blob;
1287
}
1288
result = curl_easy_setopt(easy, tag, &blob);
1289
break;
1290
}
1291
FALLTHROUGH();
1292
case CURLOPT_ERRORBUFFER: /* This is an output buffer. */
1293
result = Curl_vsetopt(easy, tag, arg);
1294
break;
1295
}
1296
1297
va_end(arg);
1298
free(cp);
1299
return result;
1300
}
1301
1302
1303
/* ILE/RPG helper functions. */
1304
1305
char *
1306
curl_form_long_value(long value)
1307
{
1308
/* ILE/RPG cannot cast an integer to a pointer. This procedure does it. */
1309
1310
return (char *) value;
1311
}
1312
1313
1314
CURLcode
1315
curl_easy_setopt_RPGnum_(CURL *easy, CURLoption tag, curl_off_t arg)
1316
{
1317
/* ILE/RPG procedure overloading cannot discriminate between different
1318
size and/or signedness of format arguments. This provides a generic
1319
wrapper that adapts size to the given tag expectation.
1320
This procedure is not intended to be explicitly called from user code. */
1321
if(tag / 10000 != CURLOPTTYPE_OFF_T)
1322
return curl_easy_setopt(easy, tag, (long) arg);
1323
return curl_easy_setopt(easy, tag, arg);
1324
}
1325
1326
1327
CURLcode
1328
curl_multi_setopt_RPGnum_(CURLM *multi, CURLMoption tag, curl_off_t arg)
1329
{
1330
/* Likewise, for multi handle. */
1331
if(tag / 10000 != CURLOPTTYPE_OFF_T)
1332
return curl_multi_setopt(multi, tag, (long) arg);
1333
return curl_multi_setopt(multi, tag, arg);
1334
}
1335
1336
1337
char *
1338
curl_pushheader_bynum_cssid(struct curl_pushheaders *h,
1339
size_t num, unsigned int ccsid)
1340
{
1341
char *d = (char *) NULL;
1342
char *s = curl_pushheader_bynum(h, num);
1343
1344
if(s)
1345
d = dynconvert(ccsid, s, -1, ASCII_CCSID);
1346
1347
return d;
1348
}
1349
1350
1351
char *
1352
curl_pushheader_byname_ccsid(struct curl_pushheaders *h, const char *header,
1353
unsigned int ccsidin, unsigned int ccsidout)
1354
{
1355
char *d = (char *) NULL;
1356
1357
if(header) {
1358
header = dynconvert(ASCII_CCSID, header, -1, ccsidin);
1359
1360
if(header) {
1361
char *s = curl_pushheader_byname(h, header);
1362
free((char *) header);
1363
1364
if(s)
1365
d = dynconvert(ccsidout, s, -1, ASCII_CCSID);
1366
}
1367
}
1368
1369
return d;
1370
}
1371
1372
static CURLcode
1373
mime_string_call(curl_mimepart *part, const char *string, unsigned int ccsid,
1374
CURLcode (*mimefunc)(curl_mimepart *part, const char *string))
1375
{
1376
char *s = (char *) NULL;
1377
CURLcode result;
1378
1379
if(!string)
1380
return mimefunc(part, string);
1381
s = dynconvert(ASCII_CCSID, string, -1, ccsid);
1382
if(!s)
1383
return CURLE_OUT_OF_MEMORY;
1384
1385
result = mimefunc(part, s);
1386
free(s);
1387
return result;
1388
}
1389
1390
CURLcode
1391
curl_mime_name_ccsid(curl_mimepart *part, const char *name, unsigned int ccsid)
1392
{
1393
return mime_string_call(part, name, ccsid, curl_mime_name);
1394
}
1395
1396
CURLcode
1397
curl_mime_filename_ccsid(curl_mimepart *part,
1398
const char *filename, unsigned int ccsid)
1399
{
1400
return mime_string_call(part, filename, ccsid, curl_mime_filename);
1401
}
1402
1403
CURLcode
1404
curl_mime_type_ccsid(curl_mimepart *part,
1405
const char *mimetype, unsigned int ccsid)
1406
{
1407
return mime_string_call(part, mimetype, ccsid, curl_mime_type);
1408
}
1409
1410
CURLcode
1411
curl_mime_encoder_ccsid(curl_mimepart *part,
1412
const char *encoding, unsigned int ccsid)
1413
{
1414
return mime_string_call(part, encoding, ccsid, curl_mime_encoder);
1415
}
1416
1417
CURLcode
1418
curl_mime_filedata_ccsid(curl_mimepart *part,
1419
const char *filename, unsigned int ccsid)
1420
{
1421
return mime_string_call(part, filename, ccsid, curl_mime_filedata);
1422
}
1423
1424
CURLcode
1425
curl_mime_data_ccsid(curl_mimepart *part,
1426
const char *data, size_t datasize, unsigned int ccsid)
1427
{
1428
char *s = (char *) NULL;
1429
CURLcode result;
1430
1431
if(!data)
1432
return curl_mime_data(part, data, datasize);
1433
s = dynconvert(ASCII_CCSID, data, datasize, ccsid);
1434
if(!s)
1435
return CURLE_OUT_OF_MEMORY;
1436
1437
result = curl_mime_data(part, s, datasize);
1438
free(s);
1439
return result;
1440
}
1441
1442
CURLUcode
1443
curl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part,
1444
unsigned int flags, unsigned int ccsid)
1445
{
1446
char *s = (char *)NULL;
1447
CURLUcode result;
1448
1449
if(!part)
1450
return CURLUE_BAD_PARTPOINTER;
1451
1452
*part = (char *)NULL;
1453
result = curl_url_get(handle, what, &s, flags);
1454
if(result == CURLUE_OK) {
1455
if(s) {
1456
*part = dynconvert(ccsid, s, -1, ASCII_CCSID);
1457
if(!*part)
1458
result = CURLUE_OUT_OF_MEMORY;
1459
}
1460
}
1461
if(s)
1462
free(s);
1463
return result;
1464
}
1465
1466
CURLUcode
1467
curl_url_set_ccsid(CURLU *handle, CURLUPart what, const char *part,
1468
unsigned int flags, unsigned int ccsid)
1469
{
1470
char *s = (char *)NULL;
1471
CURLUcode result;
1472
1473
if(part) {
1474
s = dynconvert(ASCII_CCSID, part, -1, ccsid);
1475
if(!s)
1476
return CURLUE_OUT_OF_MEMORY;
1477
}
1478
result = curl_url_set(handle, what, s, flags);
1479
if(s)
1480
free(s);
1481
return result;
1482
}
1483
1484
const struct curl_easyoption *
1485
curl_easy_option_by_name_ccsid(const char *name, unsigned int ccsid)
1486
{
1487
const struct curl_easyoption *option = NULL;
1488
1489
if(name) {
1490
char *s = dynconvert(ASCII_CCSID, name, -1, ccsid);
1491
1492
if(s) {
1493
option = curl_easy_option_by_name(s);
1494
free(s);
1495
}
1496
}
1497
1498
return option;
1499
}
1500
1501
/* Return option name in the given ccsid. */
1502
const char *
1503
curl_easy_option_get_name_ccsid(const struct curl_easyoption *option,
1504
unsigned int ccsid)
1505
{
1506
char *name = NULL;
1507
1508
if(option && option->name)
1509
name = dynconvert(ccsid, option->name, -1, ASCII_CCSID);
1510
1511
return (const char *) name;
1512
}
1513
1514
/* Header API CCSID support. */
1515
CURLHcode
1516
curl_easy_header_ccsid(CURL *easy, const char *name, size_t index,
1517
unsigned int origin, int request,
1518
struct curl_header **hout, unsigned int ccsid)
1519
{
1520
CURLHcode result = CURLHE_BAD_ARGUMENT;
1521
1522
if(name) {
1523
char *s = dynconvert(ASCII_CCSID, name, -1, ccsid);
1524
1525
result = CURLHE_OUT_OF_MEMORY;
1526
if(s) {
1527
result = curl_easy_header(easy, s, index, origin, request, hout);
1528
free(s);
1529
}
1530
}
1531
1532
return result;
1533
}
1534
1535