📄 ccsidcurl.c
字号:
/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id: ccsidcurl.c,v 1.5 2008-01-16 16:04:47 patrickm Exp $ * ***************************************************************************//* CCSID API wrappers for OS/400. */#include <iconv.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include <stdarg.h>#pragma enum(int)#include <curl/curl.h>#include "urldata.h"#include "url.h"#include "getinfo.h"#include "ccsidcurl.h"#include "os400sys.h"#ifndef SIZE_MAX#define SIZE_MAX ((size_t) ~0) /* Is unsigned on OS/400. */#endif#define ASCII_CCSID 819 /* Use ISO-8859-1 as ASCII. */#define NOCONV_CCSID 65535 /* No conversion. */#define ICONV_ID_SIZE 32 /* Size of iconv_open() code identifier. */#define ICONV_OPEN_ERROR(t) ((t).return_value == -1)#define ALLOC_GRANULE 8 /* Alloc. granule for curl_formadd_ccsid(). */static voidmakeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid){ /** *** Convert a CCSID to the corresponding IBM iconv_open() character *** code identifier. *** This code is specific to the OS400 implementation of the iconv library. *** CCSID 65535 (no conversion) is replaced by the ASCII CCSID. *** CCSID 0 is interpreted by the OS400 as the job's CCSID. **/ ccsid &= 0xFFFF; if (ccsid == NOCONV_CCSID) ccsid = ASCII_CCSID; memset(buf, 0, ICONV_ID_SIZE); curl_msprintf(buf, "IBMCCSID%05u0000000", ccsid);}static iconv_ticonv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin, unsigned int cstr){ char fromcode[ICONV_ID_SIZE]; char tocode[ICONV_ID_SIZE]; /** *** Like iconv_open(), but character codes are given as CCSIDs. *** If `cstr' is non-zero, conversion is set up to stop whenever a *** null character is encountered. *** See iconv_open() IBM description in "National Language Support API". **/ makeOS400IconvCode(fromcode, ccsidin); makeOS400IconvCode(tocode, ccsidout); memset(tocode + 13, 0, sizeof tocode - 13); /* Dest. code id format. */ if (cstr) fromcode[18] = '1'; /* Set null-terminator flag. */ return iconv_open(tocode, fromcode);}static intconvert(char * d, size_t dlen, int dccsid, const char * s, int slen, int sccsid){ int i; iconv_t cd; size_t lslen; /** *** Convert `sccsid'-coded `slen'-data bytes at `s' into `dccsid'-coded *** data stored in the `dlen'-byte buffer at `d'. *** If `slen' < 0, source string is null-terminated. *** CCSID 65535 (no conversion) is replaced by the ASCII CCSID. *** Return the converted destination byte count, or -1 if error. **/ if (sccsid == 65535) sccsid = ASCII_CCSID; if (dccsid == 65535) dccsid = ASCII_CCSID; if (sccsid == dccsid) { lslen = slen >= 0? slen: strlen(s) + 1; i = lslen < dlen? lslen: dlen; if (s != d && i > 0) memcpy(d, s, i); return i; } if (slen < 0) { lslen = 0; cd = iconv_open_CCSID(dccsid, sccsid, 1); } else { lslen = (size_t) slen; cd = iconv_open_CCSID(dccsid, sccsid, 0); } if (ICONV_OPEN_ERROR(cd)) return -1; i = dlen; if ((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0) i = -1; else i -= dlen; iconv_close(cd); return i;}static char *dynconvert(int dccsid, const char * s, int slen, int sccsid){ char * d; char * cp; size_t dlen; int l; int l2; static const char nullbyte = 0; /* Like convert, but the destination is allocated and returned. */ dlen = (size_t) (slen < 0? strlen(s): slen) + 1; dlen *= MAX_CONV_EXPANSION; /* Allow some expansion. */ d = malloc(dlen); if (!d) return (char *) NULL; l = convert(d, dlen, dccsid, s, slen, sccsid); if (l < 0) { free(d); return (char *) NULL; } if (slen < 0) { /* Need to null-terminate even when source length is given. Since destination code size is unknown, use a conversion to generate terminator. */ l2 = convert(d + l, dlen - l, dccsid, &nullbyte, -1, ASCII_CCSID); if (l2 < 0) { free(d); return (char *) NULL; } l += l2; } if ((size_t) l < dlen) { cp = realloc(d, l); /* Shorten to minimum needed. */ if (cp) d = cp; } return d;}char *curl_version_ccsid(unsigned int ccsid){ int i; char * aversion; char * eversion; aversion = curl_version(); if (!aversion) return aversion; i = strlen(aversion) + 1; i *= MAX_CONV_EXPANSION; if (!(eversion = Curl_thread_buffer(LK_CURL_VERSION, i))) return (char *) NULL; if (convert(eversion, i, ccsid, aversion, -1, ASCII_CCSID) < 0) return (char *) NULL; return eversion;}char *curl_easy_escape_ccsid(CURL * handle, const char * string, int length, unsigned int sccsid, unsigned int dccsid){ char * s; char * d; if (!string) { errno = EINVAL; return (char *) NULL; } s = dynconvert(ASCII_CCSID, s, length? length: -1, sccsid); if (!s) return (char *) NULL; d = curl_easy_escape(handle, s, 0); free(s); if (!d) return (char *) NULL; s = dynconvert(dccsid, d, -1, ASCII_CCSID); free(d); return s;}char *curl_easy_unescape_ccsid(CURL * handle, const char * string, int length, int * outlength, unsigned int sccsid, unsigned int dccsid){ char * s; char * d; if (!string) { errno = EINVAL; return (char *) NULL; } s = dynconvert(ASCII_CCSID, s, length? length: -1, sccsid); if (!s) return (char *) NULL; d = curl_easy_unescape(handle, s, 0, outlength); free(s); if (!d) return (char *) NULL; s = dynconvert(dccsid, d, -1, ASCII_CCSID); free(d); if (s && outlength) *outlength = strlen(s); return s;}struct curl_slist *curl_slist_append_ccsid(struct curl_slist * list, const char * data, unsigned int ccsid){ char * s; s = (char *) NULL; if (!data) return curl_slist_append(list, data); s = dynconvert(ASCII_CCSID, data, -1, ccsid); if (!s) return (struct curl_slist *) NULL; list = curl_slist_append(list, s); free(s); return list;}time_tcurl_getdate_ccsid(const char * p, const time_t * unused, unsigned int ccsid){ char * s; time_t t; if (!p) return curl_getdate(p, unused); s = dynconvert(ASCII_CCSID, p, -1, ccsid); if (!s) return (time_t) -1; t = curl_getdate(s, unused); free(s); return t;}static intconvert_version_info_string(const char * * stringp, char * * bufp, int * left, unsigned int ccsid){ int l; /* Helper for curl_version_info_ccsid(): convert a string if defined. Result is stored in the `*left'-byte buffer at `*bufp'. `*bufp' and `*left' are updated accordingly. Return 0 if ok, else -1. */ if (*stringp) { l = convert(*bufp, *left, ccsid, *stringp, -1, ASCII_CCSID); if (l <= 0) return -1; *stringp = *bufp; *bufp += l; *left -= l; } return 0;}curl_version_info_data *curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid){ curl_version_info_data * p; char * cp; int n; int nproto; int i; curl_version_info_data * id; /* The assertion below is possible, because although the second operand is an enum member, the first is a #define. In that case, the OS/400 C compiler seems to compare string values after substitution. */#if CURLVERSION_NOW != CURLVERSION_FOURTH#error curl_version_info_data structure has changed: upgrade this procedure too.#endif /* If caller has been compiled with a new version, error. */ if (stamp > CURLVERSION_NOW) return (curl_version_info_data *) NULL; p = curl_version_info(stamp); if (!p) return p; /* Measure thread space needed. */ n = 0; nproto = 0; if (p->protocols) { while (p->protocols[nproto]) n += strlen(p->protocols[nproto++]); n += nproto++; } if (p->version) n += strlen(p->version) + 1; if (p->host) n += strlen(p->host) + 1; if (p->ssl_version) n += strlen(p->ssl_version) + 1; if (p->libz_version) n += strlen(p->libz_version) + 1; if (p->ares) n += strlen(p->ares) + 1; if (p->libidn) n += strlen(p->libidn) + 1; if (p->libssh_version) n += strlen(p->libssh_version) + 1; /* Allocate thread space. */ n *= MAX_CONV_EXPANSION; if (nproto) n += nproto * sizeof(const char *); cp = Curl_thread_buffer(LK_VERSION_INFO_DATA, n); id = (curl_version_info_data *) Curl_thread_buffer(LK_VERSION_INFO, sizeof *id); if (!id || !cp) return (curl_version_info_data *) NULL; /* Copy data and convert strings. */ memcpy((char *) id, (char *) p, sizeof *p); if (id->protocols) { id->protocols = (const char * const *) cp; i = nproto * sizeof id->protocols[0]; memcpy(cp, (char *) p->protocols, i); cp += i; n -= i; for (i = 0; id->protocols[i]; i++) if (convert_version_info_string(((const char * *) id->protocols) + i, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; } if (convert_version_info_string(&id->version, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; if (convert_version_info_string(&id->host, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; if (convert_version_info_string(&id->ssl_version, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; if (convert_version_info_string(&id->libz_version, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; if (convert_version_info_string(&id->ares, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; if (convert_version_info_string(&id->libidn, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; if (convert_version_info_string(&id->libssh_version, &cp, &n, ccsid)) return (curl_version_info_data *) NULL; return id;}const char *curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid){ int i; const char * s; char * buf; s = curl_easy_strerror(error); if (!s) return s; i = MAX_CONV_EXPANSION * (strlen(s) + 1); if (!(buf = Curl_thread_buffer(LK_EASY_STRERROR, i))) return (const char *) NULL; if (convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0) return (const char *) NULL; return (const char *) buf;}const char *curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid){ int i; const char * s; char * buf; s = curl_share_strerror(error); if (!s) return s; i = MAX_CONV_EXPANSION * (strlen(s) + 1); if (!(buf = Curl_thread_buffer(LK_SHARE_STRERROR, i))) return (const char *) NULL; if (convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0) return (const char *) NULL; return (const char *) buf;}const char *curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid){ int i; const char * s; char * buf; s = curl_multi_strerror(error); if (!s) return s; i = MAX_CONV_EXPANSION * (strlen(s) + 1); if (!(buf = Curl_thread_buffer(LK_MULTI_STRERROR, i))) return (const char *) NULL; if (convert(buf, i, ccsid, s, -1, ASCII_CCSID) < 0) return (const char *) NULL; return (const char *) buf;}CURLcodecurl_easy_getinfo_ccsid(CURL * curl, CURLINFO info, ...){ va_list arg; void * paramp; CURLcode ret; unsigned int ccsid; char * * cpp; char * s; char * d; struct SessionHandle * data; /* WARNING: unlike curl_easy_get_info(), the strings returned by this procedure have to be free'ed. */ data = (struct SessionHandle *) curl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -