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