ccsidcurl.c (35884B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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 }