1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, 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 http://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#include "setup.h"
23
24#ifdef CURL_DOES_CONVERSIONS
25
26#ifdef HAVE_ICONV
27#  include <iconv.h>
28#endif
29
30#include <curl/curl.h>
31
32#include "tool_convert.h"
33
34#include "memdebug.h" /* keep this as LAST include */
35
36#ifdef HAVE_ICONV
37
38/* curl tool iconv conversion descriptors */
39static iconv_t inbound_cd  = (iconv_t)-1;
40static iconv_t outbound_cd = (iconv_t)-1;
41
42/* set default codesets for iconv */
43#ifndef CURL_ICONV_CODESET_OF_NETWORK
44#  define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
45#endif
46
47/*
48 * convert_to_network() is a curl tool function to convert
49 * from the host encoding to ASCII on non-ASCII platforms.
50 */
51CURLcode convert_to_network(char *buffer, size_t length)
52{
53  /* translate from the host encoding to the network encoding */
54  char *input_ptr, *output_ptr;
55  size_t res, in_bytes, out_bytes;
56
57  /* open an iconv conversion descriptor if necessary */
58  if(outbound_cd == (iconv_t)-1) {
59    outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
60                             CURL_ICONV_CODESET_OF_HOST);
61    if(outbound_cd == (iconv_t)-1) {
62      return CURLE_CONV_FAILED;
63    }
64  }
65  /* call iconv */
66  input_ptr = output_ptr = buffer;
67  in_bytes = out_bytes = length;
68  res = iconv(outbound_cd, &input_ptr,  &in_bytes,
69              &output_ptr, &out_bytes);
70  if((res == (size_t)-1) || (in_bytes != 0)) {
71    return CURLE_CONV_FAILED;
72  }
73
74  return CURLE_OK;
75}
76
77/*
78 * convert_from_network() is a curl tool function
79 * for performing ASCII conversions on non-ASCII platforms.
80 */
81CURLcode convert_from_network(char *buffer, size_t length)
82{
83  /* translate from the network encoding to the host encoding */
84  char *input_ptr, *output_ptr;
85  size_t res, in_bytes, out_bytes;
86
87  /* open an iconv conversion descriptor if necessary */
88  if(inbound_cd == (iconv_t)-1) {
89    inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
90                            CURL_ICONV_CODESET_OF_NETWORK);
91    if(inbound_cd == (iconv_t)-1) {
92      return CURLE_CONV_FAILED;
93    }
94  }
95  /* call iconv */
96  input_ptr = output_ptr = buffer;
97  in_bytes = out_bytes = length;
98  res = iconv(inbound_cd, &input_ptr,  &in_bytes,
99              &output_ptr, &out_bytes);
100  if((res == (size_t)-1) || (in_bytes != 0)) {
101    return CURLE_CONV_FAILED;
102  }
103
104  return CURLE_OK;
105}
106
107void convert_cleanup(void)
108{
109  /* close iconv conversion descriptors */
110  if(inbound_cd != (iconv_t)-1)
111    (void)iconv_close(inbound_cd);
112  if(outbound_cd != (iconv_t)-1)
113    (void)iconv_close(outbound_cd);
114}
115
116#endif /* HAVE_ICONV */
117
118char convert_char(curl_infotype infotype, char this_char)
119{
120/* determine how this specific character should be displayed */
121  switch(infotype) {
122  case CURLINFO_DATA_IN:
123  case CURLINFO_DATA_OUT:
124  case CURLINFO_SSL_DATA_IN:
125  case CURLINFO_SSL_DATA_OUT:
126    /* data, treat as ASCII */
127    if((this_char >= 0x20) && (this_char < 0x7f)) {
128      /* printable ASCII hex value: convert to host encoding */
129      (void)convert_from_network(&this_char, 1);
130    }
131    else {
132      /* non-printable ASCII, use a replacement character */
133      return UNPRINTABLE_CHAR;
134    }
135    /* fall through to default */
136  default:
137    /* treat as host encoding */
138    if(ISPRINT(this_char)
139       &&  (this_char != '\t')
140       &&  (this_char != '\r')
141       &&  (this_char != '\n')) {
142      /* printable characters excluding tabs and line end characters */
143      return this_char;
144    }
145    break;
146  }
147  /* non-printable, use a replacement character  */
148  return UNPRINTABLE_CHAR;
149}
150
151#endif /* CURL_DOES_CONVERSIONS */
152
153