ccsidcurl.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  *
00022  ***************************************************************************/
00023 
00024 /* CCSID API wrappers for OS/400. */
00025 
00026 #include <iconv.h>
00027 #include <string.h>
00028 #include <stdlib.h>
00029 #include <errno.h>
00030 #include <stdarg.h>
00031 
00032 #pragma enum(int)
00033 
00034 #include "curl.h"
00035 #include "mprintf.h"
00036 #include "slist.h"
00037 #include "urldata.h"
00038 #include "url.h"
00039 #include "getinfo.h"
00040 #include "ccsidcurl.h"
00041 
00042 #include "os400sys.h"
00043 
00044 #ifndef SIZE_MAX
00045 #define SIZE_MAX        ((size_t) ~0)   /* Is unsigned on OS/400. */
00046 #endif
00047 
00048 
00049 #define ASCII_CCSID     819     /* Use ISO-8859-1 as ASCII. */
00050 #define NOCONV_CCSID    65535   /* No conversion. */
00051 #define ICONV_ID_SIZE   32      /* Size of iconv_open() code identifier. */
00052 #define ICONV_OPEN_ERROR(t)     ((t).return_value == -1)
00053 
00054 #define ALLOC_GRANULE   8       /* Alloc. granule for curl_formadd_ccsid(). */
00055 
00056 
00057 static void
00058 makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
00059 
00060 {
00069   ccsid &= 0xFFFF;
00070 
00071   if(ccsid == NOCONV_CCSID)
00072     ccsid = ASCII_CCSID;
00073 
00074   memset(buf, 0, ICONV_ID_SIZE);
00075   curl_msprintf(buf, "IBMCCSID%05u0000000", ccsid);
00076 }
00077 
00078 
00079 static iconv_t
00080 iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin,
00081                                                         unsigned int cstr)
00082 
00083 {
00084   char fromcode[ICONV_ID_SIZE];
00085   char tocode[ICONV_ID_SIZE];
00086 
00094   makeOS400IconvCode(fromcode, ccsidin);
00095   makeOS400IconvCode(tocode, ccsidout);
00096   memset(tocode + 13, 0, sizeof tocode - 13);   /* Dest. code id format. */
00097 
00098   if(cstr)
00099     fromcode[18] = '1';                         /* Set null-terminator flag. */
00100 
00101   return iconv_open(tocode, fromcode);
00102 }
00103 
00104 
00105 static int
00106 convert(char * d, size_t dlen, int dccsid,
00107         const char * s, int slen, int sccsid)
00108 
00109 {
00110   int i;
00111   iconv_t cd;
00112   size_t lslen;
00113 
00122   if(sccsid == 65535)
00123     sccsid = ASCII_CCSID;
00124 
00125   if(dccsid == 65535)
00126     dccsid = ASCII_CCSID;
00127 
00128   if(sccsid == dccsid) {
00129     lslen = slen >= 0? slen: strlen(s) + 1;
00130     i = lslen < dlen? lslen: dlen;
00131 
00132     if(s != d && i > 0)
00133       memcpy(d, s, i);
00134 
00135     return i;
00136     }
00137 
00138   if(slen < 0) {
00139     lslen = 0;
00140     cd = iconv_open_CCSID(dccsid, sccsid, 1);
00141     }
00142   else {
00143     lslen = (size_t) slen;
00144     cd = iconv_open_CCSID(dccsid, sccsid, 0);
00145     }
00146 
00147   if(ICONV_OPEN_ERROR(cd))
00148     return -1;
00149 
00150   i = dlen;
00151 
00152   if((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0)
00153     i = -1;
00154   else
00155     i -= dlen;
00156 
00157   iconv_close(cd);
00158   return i;
00159 }
00160 
00161 
00162 static char *
00163 dynconvert(int dccsid, const char * s, int slen, int sccsid)
00164 
00165 {
00166   char * d;
00167   char * cp;
00168   size_t dlen;
00169   int l;
00170   static const char nullbyte = 0;
00171 
00172   /* Like convert, but the destination is allocated and returned. */
00173 
00174   dlen = (size_t) (slen < 0? strlen(s): slen) + 1;
00175   dlen *= MAX_CONV_EXPANSION;           /* Allow some expansion. */
00176   d = malloc(dlen);
00177 
00178   if(!d)
00179     return (char *) NULL;
00180 
00181   l = convert(d, dlen, dccsid, s, slen, sccsid);
00182 
00183   if(l < 0) {
00184     free(d);
00185     return (char *) NULL;
00186     }
00187 
00188   if(slen < 0) {
00189     /* Need to null-terminate even when source length is given.
00190        Since destination code size is unknown, use a conversion to generate
00191        terminator. */
00192 
00193     int l2 = convert(d + l, dlen - l, dccsid, &nullbyte, -1, ASCII_CCSID);
00194 
00195     if(l2 < 0) {
00196       free(d);
00197       return (char *) NULL;
00198       }
00199 
00200     l += l2;
00201     }
00202 
00203   if((size_t) l < dlen) {
00204     cp = realloc(d, l);         /* Shorten to minimum needed. */
00205 
00206     if(cp)
00207       d = cp;
00208     }
00209 
00210   return d;
00211 }
00212 
00213 
00214 static struct curl_slist *
00215 slist_convert(int dccsid, struct curl_slist * from, int sccsid)
00216 
00217 {
00218   struct curl_slist * to = (struct curl_slist *) NULL;
00219 
00220   for(; from; from = from->next) {
00221     char * cp = dynconvert(dccsid, from->data, -1, sccsid);
00222 
00223     if(!cp) {
00224       curl_slist_free_all(to);
00225       return (struct curl_slist *) NULL;
00226     }
00227     to = Curl_slist_append_nodup(to, cp);
00228   }
00229   return to;
00230 }
00231 
00232 
00233 char *
00234 curl_version_ccsid(unsigned int ccsid)
00235 
00236 {
00237   int i;
00238   char * aversion;
00239   char * eversion;
00240 
00241   aversion = curl_version();
00242 
00243   if(!aversion)
00244     return aversion;
00245 
00246   i = strlen(aversion) + 1;
00247   i *= MAX_CONV_EXPANSION;
00248 
00249   if(!(eversion = Curl_thread_buffer(LK_CURL_VERSION, i)))
00250     return (char *) NULL;
00251 
00252   if(convert(eversion, i, ccsid, aversion, -1, ASCII_CCSID) < 0)
00253     return (char *) NULL;
00254 
00255   return eversion;
00256 }
00257 
00258 
00259 char *
00260 curl_easy_escape_ccsid(CURL * handle, const char * string, int length,
00261                        unsigned int sccsid, unsigned int dccsid)
00262 
00263 {
00264   char * s;
00265   char * d;
00266 
00267   if(!string) {
00268     errno = EINVAL;
00269     return (char *) NULL;
00270     }
00271 
00272   s = dynconvert(ASCII_CCSID, string, length? length: -1, sccsid);
00273 
00274   if(!s)
00275     return (char *) NULL;
00276 
00277   d = curl_easy_escape(handle, s, 0);
00278   free(s);
00279 
00280   if(!d)
00281     return (char *) NULL;
00282 
00283   s = dynconvert(dccsid, d, -1, ASCII_CCSID);
00284   free(d);
00285   return s;
00286 }
00287 
00288 
00289 char *
00290 curl_easy_unescape_ccsid(CURL * handle, const char * string, int length,
00291                          int * outlength,
00292                          unsigned int sccsid, unsigned int dccsid)
00293 
00294 {
00295   char * s;
00296   char * d;
00297 
00298   if(!string) {
00299     errno = EINVAL;
00300     return (char *) NULL;
00301     }
00302 
00303   s = dynconvert(ASCII_CCSID, string, length? length: -1, sccsid);
00304 
00305   if(!s)
00306     return (char *) NULL;
00307 
00308   d = curl_easy_unescape(handle, s, 0, outlength);
00309   free(s);
00310 
00311   if(!d)
00312     return (char *) NULL;
00313 
00314   s = dynconvert(dccsid, d, -1, ASCII_CCSID);
00315   free(d);
00316 
00317   if(s && outlength)
00318     *outlength = strlen(s);
00319 
00320   return s;
00321 }
00322 
00323 
00324 struct curl_slist *
00325 curl_slist_append_ccsid(struct curl_slist * list,
00326                         const char * data, unsigned int ccsid)
00327 
00328 {
00329   char * s;
00330 
00331   s = (char *) NULL;
00332 
00333   if(!data)
00334     return curl_slist_append(list, data);
00335 
00336   s = dynconvert(ASCII_CCSID, data, -1, ccsid);
00337 
00338   if(!s)
00339     return (struct curl_slist *) NULL;
00340 
00341   list = curl_slist_append(list, s);
00342   free(s);
00343   return list;
00344 }
00345 
00346 
00347 time_t
00348 curl_getdate_ccsid(const char * p, const time_t * unused, unsigned int ccsid)
00349 
00350 {
00351   char * s;
00352   time_t t;
00353 
00354   if(!p)
00355     return curl_getdate(p, unused);
00356 
00357   s = dynconvert(ASCII_CCSID, p, -1, ccsid);
00358 
00359   if(!s)
00360     return (time_t) -1;
00361 
00362   t = curl_getdate(s, unused);
00363   free(s);
00364   return t;
00365 }
00366 
00367 
00368 static int
00369 convert_version_info_string(const char * * stringp,
00370                             char * * bufp, int * left, unsigned int ccsid)
00371 
00372 {
00373   /* Helper for curl_version_info_ccsid(): convert a string if defined.
00374      Result is stored in the `*left'-byte buffer at `*bufp'.
00375      `*bufp' and `*left' are updated accordingly.
00376      Return 0 if ok, else -1. */
00377 
00378   if(*stringp) {
00379     int l = convert(*bufp, *left, ccsid, *stringp, -1, ASCII_CCSID);
00380 
00381     if(l <= 0)
00382       return -1;
00383 
00384     *stringp = *bufp;
00385     *bufp += l;
00386     *left -= l;
00387     }
00388 
00389   return 0;
00390 }
00391 
00392 
00393 curl_version_info_data *
00394 curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid)
00395 
00396 {
00397   curl_version_info_data * p;
00398   char * cp;
00399   int n;
00400   int nproto;
00401   curl_version_info_data * id;
00402 
00403   /* The assertion below is possible, because although the second operand
00404      is an enum member, the first is a #define. In that case, the OS/400 C
00405      compiler seems to compare string values after substitution. */
00406 
00407 #if CURLVERSION_NOW != CURLVERSION_FOURTH
00408 #error curl_version_info_data structure has changed: upgrade this procedure.
00409 #endif
00410 
00411   /* If caller has been compiled with a new version, error. */
00412 
00413   if(stamp > CURLVERSION_NOW)
00414     return (curl_version_info_data *) NULL;
00415 
00416   p = curl_version_info(stamp);
00417 
00418   if(!p)
00419     return p;
00420 
00421   /* Measure thread space needed. */
00422 
00423   n = 0;
00424   nproto = 0;
00425 
00426   if(p->protocols) {
00427     while(p->protocols[nproto])
00428       n += strlen(p->protocols[nproto++]);
00429 
00430     n += nproto++;
00431     }
00432 
00433   if(p->version)
00434     n += strlen(p->version) + 1;
00435 
00436   if(p->host)
00437     n += strlen(p->host) + 1;
00438 
00439   if(p->ssl_version)
00440     n += strlen(p->ssl_version) + 1;
00441 
00442   if(p->libz_version)
00443     n += strlen(p->libz_version) + 1;
00444 
00445   if(p->ares)
00446     n += strlen(p->ares) + 1;
00447 
00448   if(p->libidn)
00449     n += strlen(p->libidn) + 1;
00450 
00451   if(p->libssh_version)
00452     n += strlen(p->libssh_version) + 1;
00453 
00454   /* Allocate thread space. */
00455 
00456   n *= MAX_CONV_EXPANSION;
00457 
00458   if(nproto)
00459     n += nproto * sizeof(const char *);
00460 
00461   cp = Curl_thread_buffer(LK_VERSION_INFO_DATA, n);
00462   id = (curl_version_info_data *) Curl_thread_buffer(LK_VERSION_INFO,
00463                                                      sizeof *id);
00464 
00465   if(!id || !cp)
00466     return (curl_version_info_data *) NULL;
00467 
00468   /* Copy data and convert strings. */
00469 
00470   memcpy((char *) id, (char *) p, sizeof *p);
00471 
00472   if(id->protocols) {
00473     int i = nproto * sizeof id->protocols[0];
00474 
00475     id->protocols = (const char * const *) cp;
00476     memcpy(cp, (char *) p->protocols, i);
00477     cp += i;
00478     n -= i;
00479 
00480     for(i = 0; id->protocols[i]; i++)
00481       if(convert_version_info_string(((const char * *) id->protocols) + i,
00482                                       &cp, &n, ccsid))
00483         return (curl_version_info_data *) NULL;
00484     }
00485 
00486   if(convert_version_info_string(&id->version, &cp, &n, ccsid))
00487     return (curl_version_info_data *) NULL;
00488 
00489   if(convert_version_info_string(&id->host, &cp, &n, ccsid))
00490     return (curl_version_info_data *) NULL;
00491 
00492   if(convert_version_info_string(&id->ssl_version, &cp, &n, ccsid))
00493     return (curl_version_info_data *) NULL;
00494 
00495   if(convert_version_info_string(&id->libz_version, &cp, &n, ccsid))
00496     return (curl_version_info_data *) NULL;
00497 
00498   if(convert_version_info_string(&id->ares, &cp, &n, ccsid))
00499     return (curl_version_info_data *) NULL;
00500 
00501   if(convert_version_info_string(&id->libidn, &cp, &n, ccsid))
00502     return (curl_version_info_data *) NULL;
00503 
00504   if(convert_version_info_string(&id->libssh_version, &cp, &n, ccsid))
00505     return (curl_version_info_data *) NULL;
00506 
00507   return id;
00508 }
00509 
00510 
00511 const char *
00512 curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid)
00513 
00514 {
00515   int i;
00516   const char * s;
00517   char * buf;
00518 
00519   s = curl_easy_strerror(error);
00520 
00521   if(!s)
00522     return s;
00523 
00524   i = MAX_CONV_EXPANSION * (strlen(s) + 1);
00525 
00526   if(!(buf = Curl_thread_buffer(LK_EASY_STRERROR, i)))
00527     return (const char *) NULL;
00528 
00529   if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
00530     return (const char *) NULL;
00531 
00532   return (const char *) buf;
00533 }
00534 
00535 
00536 const char *
00537 curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid)
00538 
00539 {
00540   int i;
00541   const char * s;
00542   char * buf;
00543 
00544   s = curl_share_strerror(error);
00545 
00546   if(!s)
00547     return s;
00548 
00549   i = MAX_CONV_EXPANSION * (strlen(s) + 1);
00550 
00551   if(!(buf = Curl_thread_buffer(LK_SHARE_STRERROR, i)))
00552     return (const char *) NULL;
00553 
00554   if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
00555     return (const char *) NULL;
00556 
00557   return (const char *) buf;
00558 }
00559 
00560 
00561 const char *
00562 curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid)
00563 
00564 {
00565   int i;
00566   const char * s;
00567   char * buf;
00568 
00569   s = curl_multi_strerror(error);
00570 
00571   if(!s)
00572     return s;
00573 
00574   i = MAX_CONV_EXPANSION * (strlen(s) + 1);
00575 
00576   if(!(buf = Curl_thread_buffer(LK_MULTI_STRERROR, i)))
00577     return (const char *) NULL;
00578 
00579   if(convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0)
00580     return (const char *) NULL;
00581 
00582   return (const char *) buf;
00583 }
00584 
00585 
00586 void
00587 curl_certinfo_free_all(struct curl_certinfo *info)
00588 
00589 {
00590   /* Free all memory used by certificate info. */
00591   if(info) {
00592     if(info->certinfo) {
00593       int i;
00594 
00595       for(i = 0; i < info->num_of_certs; i++)
00596         curl_slist_free_all(info->certinfo[i]);
00597       free((char *) info->certinfo);
00598     }
00599     free((char *) info);
00600   }
00601 }
00602 
00603 
00604 CURLcode
00605 curl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...)
00606 
00607 {
00608   va_list arg;
00609   void * paramp;
00610   CURLcode ret;
00611   unsigned int ccsid;
00612   char * * cpp;
00613   struct Curl_easy * data;
00614   struct curl_slist * * slp;
00615   struct curl_certinfo * cipf;
00616   struct curl_certinfo * cipt;
00617 
00618   /* WARNING: unlike curl_easy_getinfo(), the strings returned by this
00619      procedure have to be free'ed. */
00620 
00621   data = (struct Curl_easy *) curl;
00622   va_start(arg, info);
00623   paramp = va_arg(arg, void *);
00624   ret = Curl_getinfo(data, info, paramp);
00625 
00626   if(ret == CURLE_OK)
00627     switch ((int) info & CURLINFO_TYPEMASK) {
00628 
00629     case CURLINFO_STRING:
00630       ccsid = va_arg(arg, unsigned int);
00631       cpp = (char * *) paramp;
00632 
00633       if(*cpp) {
00634         *cpp = dynconvert(ccsid, *cpp, -1, ASCII_CCSID);
00635 
00636         if(!*cpp)
00637           ret = CURLE_OUT_OF_MEMORY;
00638       }
00639 
00640       break;
00641 
00642     case CURLINFO_SLIST:
00643       ccsid = va_arg(arg, unsigned int);
00644       switch (info) {
00645       case CURLINFO_CERTINFO:
00646         cipf = *(struct curl_certinfo * *) paramp;
00647         if(cipf) {
00648           if(!(cipt = (struct curl_certinfo *) malloc(sizeof *cipt)))
00649             ret = CURLE_OUT_OF_MEMORY;
00650           else {
00651             cipt->certinfo = (struct curl_slist * *)
00652                              calloc(cipf->num_of_certs +
00653                                     1, sizeof(struct curl_slist *));
00654             if(!cipt->certinfo)
00655               ret = CURLE_OUT_OF_MEMORY;
00656             else {
00657               int i;
00658 
00659               cipt->num_of_certs = cipf->num_of_certs;
00660               for(i = 0; i < cipf->num_of_certs; i++)
00661                 if(cipf->certinfo[i])
00662                   if(!(cipt->certinfo[i] = slist_convert(ccsid,
00663                                                           cipf->certinfo[i],
00664                                                           ASCII_CCSID))) {
00665                     ret = CURLE_OUT_OF_MEMORY;
00666                     break;
00667                   }
00668               }
00669             }
00670 
00671           if(ret != CURLE_OK) {
00672             curl_certinfo_free_all(cipt);
00673             cipt = (struct curl_certinfo *) NULL;
00674           }
00675 
00676           *(struct curl_certinfo * *) paramp = cipt;
00677         }
00678 
00679         break;
00680 
00681       case CURLINFO_TLS_SESSION:
00682       case CURLINFO_TLS_SSL_PTR:
00683       case CURLINFO_SOCKET:
00684         break;
00685 
00686       default:
00687         slp = (struct curl_slist * *) paramp;
00688         if(*slp)
00689           if(!(*slp = slist_convert(ccsid, *slp, ASCII_CCSID)))
00690             ret = CURLE_OUT_OF_MEMORY;
00691         break;
00692       }
00693     }
00694 
00695   va_end(arg);
00696   return ret;
00697 }
00698 
00699 
00700 static int
00701 Curl_is_formadd_string(CURLformoption option)
00702 
00703 {
00704   switch (option) {
00705 
00706   case CURLFORM_FILENAME:
00707   case CURLFORM_CONTENTTYPE:
00708   case CURLFORM_BUFFER:
00709   case CURLFORM_FILE:
00710   case CURLFORM_FILECONTENT:
00711   case CURLFORM_COPYCONTENTS:
00712   case CURLFORM_COPYNAME:
00713     return 1;
00714   }
00715 
00716   return 0;
00717 }
00718 
00719 
00720 static void
00721 Curl_formadd_release_local(struct curl_forms * forms, int nargs, int skip)
00722 
00723 {
00724   while(nargs--)
00725     if(nargs != skip)
00726       if(Curl_is_formadd_string(forms[nargs].option))
00727         if(forms[nargs].value)
00728           free((char *) forms[nargs].value);
00729 
00730   free((char *) forms);
00731 }
00732 
00733 
00734 static int
00735 Curl_formadd_convert(struct curl_forms * forms,
00736                      int formx, int lengthx, unsigned int ccsid)
00737 
00738 {
00739   int l;
00740   char * cp;
00741   char * cp2;
00742 
00743   if(formx < 0 || !forms[formx].value)
00744     return 0;
00745 
00746   if(lengthx >= 0)
00747     l = (int) forms[lengthx].value;
00748   else
00749     l = strlen(forms[formx].value) + 1;
00750 
00751   cp = malloc(MAX_CONV_EXPANSION * l);
00752 
00753   if(!cp)
00754     return -1;
00755 
00756   l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID,
00757               forms[formx].value, l, ccsid);
00758 
00759   if(l < 0) {
00760     free(cp);
00761     return -1;
00762     }
00763 
00764   cp2 = realloc(cp, l);         /* Shorten buffer to the string size. */
00765 
00766   if(cp2)
00767     cp = cp2;
00768 
00769   forms[formx].value = cp;
00770 
00771   if(lengthx >= 0)
00772     forms[lengthx].value = (char *) l;  /* Update length after conversion. */
00773 
00774   return l;
00775 }
00776 
00777 
00778 CURLFORMcode
00779 curl_formadd_ccsid(struct curl_httppost * * httppost,
00780                    struct curl_httppost * * last_post, ...)
00781 
00782 {
00783   va_list arg;
00784   CURLformoption option;
00785   CURLFORMcode result;
00786   struct curl_forms * forms;
00787   struct curl_forms * lforms;
00788   struct curl_forms * tforms;
00789   unsigned int lformlen;
00790   const char * value;
00791   unsigned int ccsid;
00792   int nargs;
00793   int namex;
00794   int namelengthx;
00795   int contentx;
00796   int lengthx;
00797   unsigned int contentccsid;
00798   unsigned int nameccsid;
00799 
00800   /* A single curl_formadd() call cannot be splitted in several calls to deal
00801      with all parameters: the original parameters are thus copied to a local
00802      curl_forms array and converted to ASCII when needed.
00803      CURLFORM_PTRNAME is processed as if it were CURLFORM_COPYNAME.
00804      CURLFORM_COPYNAME and CURLFORM_NAMELENGTH occurrence order in
00805      parameters is not defined; for this reason, the actual conversion is
00806      delayed to the end of parameter processing. The same applies to
00807      CURLFORM_COPYCONTENTS/CURLFORM_CONTENTSLENGTH, but these may appear
00808      several times in the parameter list; the problem resides here in knowing
00809      which CURLFORM_CONTENTSLENGTH applies to which CURLFORM_COPYCONTENTS and
00810      when we can be sure to have both info for conversion: end of parameter
00811      list is such a point, but CURLFORM_CONTENTTYPE is also used here as a
00812      natural separator between content data definitions; this seems to be
00813      in accordance with FormAdd() behavior. */
00814 
00815   /* Allocate the local curl_forms array. */
00816 
00817   lformlen = ALLOC_GRANULE;
00818   lforms = malloc(lformlen * sizeof *lforms);
00819 
00820   if(!lforms)
00821     return CURL_FORMADD_MEMORY;
00822 
00823   /* Process the arguments, copying them into local array, latching conversion
00824      indexes and converting when needed. */
00825 
00826   result = CURL_FORMADD_OK;
00827   nargs = 0;
00828   contentx = -1;
00829   lengthx = -1;
00830   namex = -1;
00831   namelengthx = -1;
00832   forms = (struct curl_forms *) NULL;
00833   va_start(arg, last_post);
00834 
00835   for(;;) {
00836     /* Make sure there is still room for an item in local array. */
00837 
00838     if(nargs >= lformlen) {
00839       lformlen += ALLOC_GRANULE;
00840       tforms = realloc(lforms, lformlen * sizeof *lforms);
00841 
00842       if(!tforms) {
00843         result = CURL_FORMADD_MEMORY;
00844         break;
00845         }
00846 
00847       lforms = tforms;
00848       }
00849 
00850     /* Get next option. */
00851 
00852     if(forms) {
00853       /* Get option from array. */
00854 
00855       option = forms->option;
00856       value = forms->value;
00857       forms++;
00858       }
00859     else {
00860       /* Get option from arguments. */
00861 
00862       option = va_arg(arg, CURLformoption);
00863 
00864       if(option == CURLFORM_END)
00865         break;
00866       }
00867 
00868     /* Dispatch by option. */
00869 
00870     switch (option) {
00871 
00872     case CURLFORM_END:
00873       forms = (struct curl_forms *) NULL;       /* Leave array mode. */
00874       continue;
00875 
00876     case CURLFORM_ARRAY:
00877       if(!forms) {
00878         forms = va_arg(arg, struct curl_forms *);
00879         continue;
00880         }
00881 
00882       result = CURL_FORMADD_ILLEGAL_ARRAY;
00883       break;
00884 
00885     case CURLFORM_COPYNAME:
00886       option = CURLFORM_PTRNAME;                /* Static for now. */
00887 
00888     case CURLFORM_PTRNAME:
00889       if(namex >= 0)
00890         result = CURL_FORMADD_OPTION_TWICE;
00891 
00892       namex = nargs;
00893 
00894       if(!forms) {
00895         value = va_arg(arg, char *);
00896         nameccsid = (unsigned int) va_arg(arg, long);
00897         }
00898       else {
00899         nameccsid = (unsigned int) forms->value;
00900         forms++;
00901         }
00902 
00903       break;
00904 
00905     case CURLFORM_COPYCONTENTS:
00906       if(contentx >= 0)
00907         result = CURL_FORMADD_OPTION_TWICE;
00908 
00909       contentx = nargs;
00910 
00911       if(!forms) {
00912         value = va_arg(arg, char *);
00913         contentccsid = (unsigned int) va_arg(arg, long);
00914         }
00915       else {
00916         contentccsid = (unsigned int) forms->value;
00917         forms++;
00918         }
00919 
00920       break;
00921 
00922     case CURLFORM_PTRCONTENTS:
00923     case CURLFORM_BUFFERPTR:
00924       if(!forms)
00925         value = va_arg(arg, char *);            /* No conversion. */
00926 
00927       break;
00928 
00929     case CURLFORM_CONTENTSLENGTH:
00930       lengthx = nargs;
00931 
00932       if(!forms)
00933         value = (char *) va_arg(arg, long);
00934 
00935       break;
00936 
00937     case CURLFORM_CONTENTLEN:
00938       lengthx = nargs;
00939 
00940       if(!forms)
00941         value = (char *) va_arg(arg, curl_off_t);
00942 
00943       break;
00944 
00945     case CURLFORM_NAMELENGTH:
00946       namelengthx = nargs;
00947 
00948       if(!forms)
00949         value = (char *) va_arg(arg, long);
00950 
00951       break;
00952 
00953     case CURLFORM_BUFFERLENGTH:
00954       if(!forms)
00955         value = (char *) va_arg(arg, long);
00956 
00957       break;
00958 
00959     case CURLFORM_CONTENTHEADER:
00960       if(!forms)
00961         value = (char *) va_arg(arg, struct curl_slist *);
00962 
00963       break;
00964 
00965     case CURLFORM_STREAM:
00966       if(!forms)
00967         value = (char *) va_arg(arg, void *);
00968 
00969       break;
00970 
00971     case CURLFORM_CONTENTTYPE:
00972       /* If a previous content has been encountered, convert it now. */
00973 
00974       if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) {
00975         result = CURL_FORMADD_MEMORY;
00976         break;
00977         }
00978 
00979       contentx = -1;
00980       lengthx = -1;
00981       /* Fall into default. */
00982 
00983     default:
00984       /* Must be a convertible string. */
00985 
00986       if(!Curl_is_formadd_string(option)) {
00987         result = CURL_FORMADD_UNKNOWN_OPTION;
00988         break;
00989         }
00990 
00991       if(!forms) {
00992         value = va_arg(arg, char *);
00993         ccsid = (unsigned int) va_arg(arg, long);
00994         }
00995       else {
00996         ccsid = (unsigned int) forms->value;
00997         forms++;
00998         }
00999 
01000       /* Do the conversion. */
01001 
01002       lforms[nargs].value = value;
01003 
01004       if(Curl_formadd_convert(lforms, nargs, -1, ccsid) < 0) {
01005         result = CURL_FORMADD_MEMORY;
01006         break;
01007         }
01008 
01009       value = lforms[nargs].value;
01010       }
01011 
01012     if(result != CURL_FORMADD_OK)
01013       break;
01014 
01015     lforms[nargs].value = value;
01016     lforms[nargs++].option = option;
01017     }
01018 
01019   va_end(arg);
01020 
01021   /* Convert the name and the last content, now that we know their lengths. */
01022 
01023   if(result == CURL_FORMADD_OK && namex >= 0) {
01024     if(Curl_formadd_convert(lforms, namex, namelengthx, nameccsid) < 0)
01025       result = CURL_FORMADD_MEMORY;
01026     else
01027       lforms[namex].option = CURLFORM_COPYNAME;         /* Force copy. */
01028     }
01029 
01030   if(result == CURL_FORMADD_OK) {
01031     if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0)
01032       result = CURL_FORMADD_MEMORY;
01033     else
01034       contentx = -1;
01035     }
01036 
01037   /* Do the formadd with our converted parameters. */
01038 
01039   if(result == CURL_FORMADD_OK) {
01040     lforms[nargs].option = CURLFORM_END;
01041     result = curl_formadd(httppost, last_post,
01042                           CURLFORM_ARRAY, lforms, CURLFORM_END);
01043     }
01044 
01045   /* Terminate. */
01046 
01047   Curl_formadd_release_local(lforms, nargs, contentx);
01048   return result;
01049 }
01050 
01051 
01052 typedef struct {
01053   curl_formget_callback append;
01054   void *                arg;
01055   unsigned int          ccsid;
01056 }   cfcdata;
01057 
01058 
01059 static size_t
01060 Curl_formget_callback_ccsid(void * arg, const char * buf, size_t len)
01061 
01062 {
01063   cfcdata * p;
01064   char * b;
01065   int l;
01066   size_t ret;
01067 
01068   p = (cfcdata *) arg;
01069 
01070   if((long) len <= 0)
01071     return (*p->append)(p->arg, buf, len);
01072 
01073   b = malloc(MAX_CONV_EXPANSION * len);
01074 
01075   if(!b)
01076     return (size_t) -1;
01077 
01078   l = convert(b, MAX_CONV_EXPANSION * len, p->ccsid, buf, len, ASCII_CCSID);
01079 
01080   if(l < 0) {
01081     free(b);
01082     return (size_t) -1;
01083     }
01084 
01085   ret = (*p->append)(p->arg, b, l);
01086   free(b);
01087   return ret == l? len: -1;
01088 }
01089 
01090 
01091 int
01092 curl_formget_ccsid(struct curl_httppost * form, void * arg,
01093                    curl_formget_callback append, unsigned int ccsid)
01094 
01095 {
01096   cfcdata lcfc;
01097 
01098   lcfc.append = append;
01099   lcfc.arg = arg;
01100   lcfc.ccsid = ccsid;
01101   return curl_formget(form, (void *) &lcfc, Curl_formget_callback_ccsid);
01102 }
01103 
01104 
01105 CURLcode
01106 curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
01107 
01108 {
01109   CURLcode result;
01110   va_list arg;
01111   struct Curl_easy * data;
01112   char * s;
01113   char * cp;
01114   unsigned int ccsid;
01115   curl_off_t pfsize;
01116   static char testwarn = 1;
01117 
01118   /* Warns if this procedure has not been updated when the dupstring enum
01119      changes.
01120      We (try to) do it only once: there is no need to issue several times
01121      the same message; but since threadsafeness is not handled here,
01122      this may occur (and we don't care!). */
01123 
01124   if(testwarn) {
01125     testwarn = 0;
01126 
01127     if((int) STRING_LASTZEROTERMINATED != (int) STRING_UNIX_SOCKET_PATH + 1 ||
01128        (int) STRING_LAST != (int) STRING_COPYPOSTFIELDS + 1)
01129       curl_mfprintf(stderr,
01130        "*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n");
01131     }
01132 
01133   data = (struct Curl_easy *) curl;
01134   va_start(arg, tag);
01135 
01136   switch (tag) {
01137 
01138   case CURLOPT_CAINFO:
01139   case CURLOPT_CAPATH:
01140   case CURLOPT_COOKIE:
01141   case CURLOPT_COOKIEFILE:
01142   case CURLOPT_COOKIEJAR:
01143   case CURLOPT_COOKIELIST:
01144   case CURLOPT_CRLFILE:
01145   case CURLOPT_CUSTOMREQUEST:
01146   case CURLOPT_DEFAULT_PROTOCOL:
01147   case CURLOPT_DNS_SERVERS:
01148   case CURLOPT_EGDSOCKET:
01149   case CURLOPT_ENCODING:
01150   case CURLOPT_FTPPORT:
01151   case CURLOPT_FTP_ACCOUNT:
01152   case CURLOPT_FTP_ALTERNATIVE_TO_USER:
01153   case CURLOPT_INTERFACE:
01154   case CURLOPT_ISSUERCERT:
01155   case CURLOPT_KEYPASSWD:
01156   case CURLOPT_KRBLEVEL:
01157   case CURLOPT_LOGIN_OPTIONS:
01158   case CURLOPT_MAIL_AUTH:
01159   case CURLOPT_MAIL_FROM:
01160   case CURLOPT_NETRC_FILE:
01161   case CURLOPT_NOPROXY:
01162   case CURLOPT_PASSWORD:
01163   case CURLOPT_PINNEDPUBLICKEY:
01164   case CURLOPT_PROXY:
01165   case CURLOPT_PROXYPASSWORD:
01166   case CURLOPT_PROXYUSERNAME:
01167   case CURLOPT_PROXYUSERPWD:
01168   case CURLOPT_PROXY_CAINFO:
01169   case CURLOPT_PROXY_CAPATH:
01170   case CURLOPT_PROXY_CRLFILE:
01171   case CURLOPT_PROXY_KEYPASSWD:
01172   case CURLOPT_PROXY_PINNEDPUBLICKEY:
01173   case CURLOPT_PROXY_SERVICE_NAME:
01174   case CURLOPT_PROXY_SSLCERT:
01175   case CURLOPT_PROXY_SSLCERTTYPE:
01176   case CURLOPT_PROXY_SSLKEY:
01177   case CURLOPT_PROXY_SSLKEYTYPE:
01178   case CURLOPT_PROXY_SSL_CIPHER_LIST:
01179   case CURLOPT_PROXY_TLSAUTH_PASSWORD:
01180   case CURLOPT_PROXY_TLSAUTH_TYPE:
01181   case CURLOPT_PROXY_TLSAUTH_USERNAME:
01182   case CURLOPT_RANDOM_FILE:
01183   case CURLOPT_RANGE:
01184   case CURLOPT_REFERER:
01185   case CURLOPT_RTSP_SESSION_ID:
01186   case CURLOPT_RTSP_STREAM_URI:
01187   case CURLOPT_RTSP_TRANSPORT:
01188   case CURLOPT_SERVICE_NAME:
01189   case CURLOPT_SOCKS5_GSSAPI_SERVICE:
01190   case CURLOPT_SOCKS_PROXY:
01191   case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
01192   case CURLOPT_SSH_KNOWNHOSTS:
01193   case CURLOPT_SSH_PRIVATE_KEYFILE:
01194   case CURLOPT_SSH_PUBLIC_KEYFILE:
01195   case CURLOPT_SSLCERT:
01196   case CURLOPT_SSLCERTTYPE:
01197   case CURLOPT_SSLENGINE:
01198   case CURLOPT_SSLKEY:
01199   case CURLOPT_SSLKEYTYPE:
01200   case CURLOPT_SSL_CIPHER_LIST:
01201   case CURLOPT_TLSAUTH_PASSWORD:
01202   case CURLOPT_TLSAUTH_TYPE:
01203   case CURLOPT_TLSAUTH_USERNAME:
01204   case CURLOPT_UNIX_SOCKET_PATH:
01205   case CURLOPT_URL:
01206   case CURLOPT_USERAGENT:
01207   case CURLOPT_USERNAME:
01208   case CURLOPT_USERPWD:
01209   case CURLOPT_XOAUTH2_BEARER:
01210     s = va_arg(arg, char *);
01211     ccsid = va_arg(arg, unsigned int);
01212 
01213     if(s) {
01214       s = dynconvert(ASCII_CCSID, s, -1, ccsid);
01215 
01216       if(!s) {
01217         result = CURLE_OUT_OF_MEMORY;
01218         break;
01219         }
01220       }
01221 
01222     result = curl_easy_setopt(curl, tag, s);
01223     free(s);
01224     break;
01225 
01226   case CURLOPT_COPYPOSTFIELDS:
01227     /* Special case: byte count may have been given by CURLOPT_POSTFIELDSIZE
01228        prior to this call. In this case, convert the given byte count and
01229        replace the length according to the conversion result. */
01230     s = va_arg(arg, char *);
01231     ccsid = va_arg(arg, unsigned int);
01232 
01233     pfsize = data->set.postfieldsize;
01234 
01235     if(!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) {
01236       result = curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, s);
01237       break;
01238       }
01239 
01240     if(pfsize == -1) {
01241       /* Data is null-terminated. */
01242       s = dynconvert(ASCII_CCSID, s, -1, ccsid);
01243 
01244       if(!s) {
01245         result = CURLE_OUT_OF_MEMORY;
01246         break;
01247         }
01248       }
01249     else {
01250       /* Data length specified. */
01251       size_t len;
01252 
01253       if(pfsize < 0 || pfsize > SIZE_MAX) {
01254         result = CURLE_OUT_OF_MEMORY;
01255         break;
01256         }
01257 
01258       len = pfsize;
01259       pfsize = len * MAX_CONV_EXPANSION;
01260 
01261       if(pfsize > SIZE_MAX)
01262         pfsize = SIZE_MAX;
01263 
01264       cp = malloc(pfsize);
01265 
01266       if(!cp) {
01267         result = CURLE_OUT_OF_MEMORY;
01268         break;
01269         }
01270 
01271       pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid);
01272 
01273       if(pfsize < 0) {
01274         free(cp);
01275         result = CURLE_OUT_OF_MEMORY;
01276         break;
01277         }
01278 
01279       data->set.postfieldsize = pfsize;         /* Replace data size. */
01280       s = cp;
01281       }
01282 
01283     result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s);
01284     data->set.str[STRING_COPYPOSTFIELDS] = s;   /* Give to library. */
01285     break;
01286 
01287   case CURLOPT_ERRORBUFFER:                     /* This is an output buffer. */
01288   default:
01289     result = Curl_setopt(data, tag, arg);
01290     break;
01291     }
01292 
01293   va_end(arg);
01294   return result;
01295 }
01296 
01297 
01298 char *
01299 curl_form_long_value(long value)
01300 
01301 {
01302   /* ILE/RPG cannot cast an integer to a pointer. This procedure does it. */
01303 
01304   return (char *) value;
01305 }
01306 
01307 
01308 char *
01309 curl_pushheader_bynum_cssid(struct curl_pushheaders *h,
01310                             size_t num, unsigned int ccsid)
01311 
01312 {
01313   char *d = (char *) NULL;
01314   char *s = curl_pushheader_bynum(h, num);
01315 
01316   if(s)
01317     d = dynconvert(ccsid, s, -1, ASCII_CCSID);
01318 
01319   return d;
01320 }
01321 
01322 
01323 char *
01324 curl_pushheader_byname_ccsid(struct curl_pushheaders *h, const char *header,
01325                              unsigned int ccsidin, unsigned int ccsidout)
01326 
01327 {
01328   char *d = (char *) NULL;
01329   char *s;
01330 
01331   if(header) {
01332     header = dynconvert(ASCII_CCSID, header, -1, ccsidin);
01333 
01334     if(header) {
01335       s = curl_pushheader_byname(h, header);
01336       free((char *) header);
01337 
01338       if(s)
01339         d = dynconvert(ccsidout, s, -1, ASCII_CCSID);
01340     }
01341   }
01342 
01343   return d;
01344 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:02