NCBI C++ ToolKit
utf8_2.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 2003, 2004 Frediano Ziglio
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include "common.h"
20 
21 #include <ctype.h>
22 
23 #include <common/test_assert.h>
24 
25 /* try conversion from utf8 to iso8859-1 */
26 
27 static TDSSOCKET *tds;
28 static int g_result = 0;
29 static int einval_error = 0;
30 static int eilseq_error = 0;
31 static int einval_count = 0;
32 static int eilseq_count = 0;
33 static int e2big_count = 0;
34 static char test_name[128];
35 
36 static int invalid_char = -1;
37 
38 static void
39 test(int n, int type)
40 {
41  int rc;
42  TDS_INT result_type;
43  char buf[1100], tmp[1024];
44  TDSCOLUMN *curcol;
45  char *src;
46  int done_flags;
47  int i;
48  char prefix[32], suffix[32];
49 
50  sprintf(test_name, "test %d len %d", type, n);
51 
52  /* do a select and check all results */
53  prefix[0] = 0;
54  suffix[0] = 0;
55  tmp[0] = 0;
56  switch (type) {
57  case 0:
58  strcpy(suffix, "C280C290");
59  break;
60  case 1:
61  /* try two invalid in different part */
62  strcpy(prefix, "C480C290");
63  strcpy(suffix, "C480C290");
64  break;
65  }
66 
67  for (i = 0; i < n; ++i)
68  sprintf(strchr(tmp, 0), "%02X", 0x30 + (i % 10));
69  sprintf(buf, "select convert(varchar(255), 0x%s%s%s)", prefix, tmp, suffix);
70  rc = tds_submit_query(tds, buf);
71  if (rc != TDS_SUCCESS) {
72  fprintf(stderr, "tds_submit_query() failed\n");
73  exit(1);
74  }
75 
76  if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCESS) {
77  fprintf(stderr, "tds_process_tokens() failed\n");
78  exit(1);
79  }
80 
81  if (result_type != TDS_ROWFMT_RESULT) {
82  fprintf(stderr, "expected row fmt() failed\n");
83  exit(1);
84  }
85 
86  if (tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS) != TDS_SUCCESS) {
87  fprintf(stderr, "tds_process_tokens() failed\n");
88  exit(1);
89  }
90 
91  if (result_type != TDS_ROW_RESULT) {
92  fprintf(stderr, "expected row result() failed\n");
93  exit(1);
94  }
95 
96  /* force tds to convert from utf8 to iso8859-1 (even on Sybase) */
97  tds_srv_charset_changed(tds->conn, "UTF-8");
99 
101  if (rc != TDS_SUCCESS) {
102  fprintf(stderr, "tds_process_tokens() failed\n");
103  exit(1);
104  }
105 
106  curcol = tds->current_results->columns[0];
107  src = (char*) curcol->column_data;
108 
109  if (is_blob_col(curcol)) {
110  TDSBLOB *blob = (TDSBLOB *) src;
111 
112  src = blob->textvalue;
113  }
114 
115  prefix[0] = 0;
116  suffix[0] = 0;
117  tmp[0] = 0;
118  switch (type) {
119  case 0:
120  strcpy(suffix, "\x80\x90");
121  break;
122  case 1:
123  /* try two invalid in different part */
124  strcpy(prefix, "?\x90");
125  strcpy(suffix, "?\x90");
126  /* some platforms replace invalid sequence with a fixed char */
127  if (invalid_char < 0)
128  invalid_char = (unsigned char) src[0];
129  prefix[0] = (char) invalid_char;
130  suffix[0] = (char) invalid_char;
131  break;
132  }
133 
134  for (i = 0; i < n; ++i)
135  sprintf(strchr(tmp, 0), "%c", "0123456789"[i % 10]);
136  sprintf(buf, "%s%s%s", prefix, tmp, suffix);
137 
138  if (strlen(buf) != curcol->column_cur_size || strncmp(buf, src, curcol->column_cur_size) != 0) {
139  int l = curcol->column_cur_size;
140 
141  if (l > 1000)
142  l = 1000;
143  strncpy(tmp, src, l);
144  tmp[l] = 0;
145  fprintf(stderr, "Wrong result in %s\n Got: '%s' len %d\n Expected: '%s' len %u\n", test_name, tmp,
146  curcol->column_cur_size, buf, (unsigned int) strlen(buf));
147  exit(1);
148  }
149 
151  if (rc != TDS_SUCCESS || result_type == TDS_ROW_RESULT) {
152  fprintf(stderr, "tds_process_tokens() unexpected return\n");
153  exit(1);
154  }
155 
156  while ((rc = tds_process_tokens(tds, &result_type, &done_flags, TDS_TOKEN_RESULTS)) == TDS_SUCCESS) {
157  switch (result_type) {
158  case TDS_NO_MORE_RESULTS:
159  break;
160 
161  case TDS_DONE_RESULT:
162  case TDS_DONEPROC_RESULT:
164  if (!(done_flags & TDS_DONE_ERROR))
165  break;
166 
167  default:
168  fprintf(stderr, "tds_process_tokens() unexpected result_type\n");
169  exit(1);
170  break;
171  }
172  }
173 }
174 
175 static int
176 err_handler(const TDSCONTEXT * tds_ctx, TDSSOCKET * tds, TDSMESSAGE * msg)
177 {
178  int error = 0;
179 
180  if (strstr(msg->message, "EINVAL")) {
181  ++einval_count;
182  if (einval_error)
183  error = 1;
184  } else if (strstr(msg->message, "could not be converted")) {
185  ++eilseq_count;
186  if (eilseq_error)
187  error = 1;
188  } else if (strstr(msg->message, "E2BIG")) {
189  ++e2big_count;
190  error = 1;
191  } else {
192  error = 1;
193  }
194 
195  if (error) {
196  fprintf(stderr, "Unexpected in %s error: %s\n", test_name, msg->message);
197  g_result = 1;
198  }
199  return TDS_INT_CANCEL;
200 }
201 
202 int
203 main(int argc, char **argv)
204 {
205  TDSLOGIN *login;
206  int ret;
207  int verbose = 0;
208  int i;
209  typedef int (*perr)(const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *);
210  const perr * my_err;
211 
212  /* use ISO8859-1 as our coding */
213  strcpy(CHARSET, "ISO8859-1");
214 
215  ret = try_tds_login(&login, &tds, __FILE__, verbose);
216  if (ret != TDS_SUCCESS) {
217  fprintf(stderr, "try_tds_login() failed\n");
218  return 1;
219  }
220 
221  /* override a const in a safe way */
222  my_err = &tds_get_ctx(tds)->err_handler;
223  *((perr*)my_err) = err_handler;
224 
225  /* prepend some characters to check part of sequence error */
226  einval_error = 1;
227  eilseq_error = 1;
228  /* do not stop on first error so we check conversion correct */
229  for (i = 0; i <= 192; ++i)
230  test(i, 0);
231 
232  /* try creating a double conversion warning */
233  eilseq_error = 0;
234  einval_error = 0; /* we already tested this error above */
235  for (i = 0; i <= 192; ++i) {
236  eilseq_count = 0;
237  test(i, 1);
238  if (eilseq_count > 1) {
239  fprintf(stderr, "Two warnings returned instead of one in %s\n", test_name);
240  g_result = 1;
241  break;
242  }
243  if (eilseq_count < 1 && invalid_char == '?') {
244  fprintf(stderr, "No warning returned in %s\n", test_name);
245  g_result = 1;
246  }
247  }
248 
250  return g_result;
251 }
#define TDS_DONEPROC_RESULT
Definition: tds.h:228
#define TDS_ROWFMT_RESULT
Definition: tds.h:224
tds_sysdep_int32_type TDS_INT
Definition: tds.h:149
@ TDS_RETURN_ROW
Definition: tds.h:256
@ TDS_STOPAT_ROWFMT
Definition: tds.h:252
@ TDS_TOKEN_RESULTS
Definition: tds.h:261
@ TDS_RETURN_COMPUTE
Definition: tds.h:257
@ TDS_RETURN_DONE
Definition: tds.h:255
#define TDS_DONE_RESULT
Definition: tds.h:227
@ client2server_chardata
Definition: tds.h:1110
#define TDS_NO_MORE_RESULTS
Definition: tds.h:202
#define TDS_INT_CANCEL
Definition: tds.h:210
#define is_blob_col(x)
Definition: tds.h:445
#define TDS_ROW_RESULT
Definition: tds.h:216
@ TDS_DONE_ERROR
error occurred
Definition: tds.h:272
#define TDS_SUCCESS
Definition: tds.h:203
#define tds_get_ctx(tds)
Definition: tds.h:1294
#define TDS_DONEINPROC_RESULT
Definition: tds.h:229
static char tmp[3200]
Definition: utf8.c:42
int main(int argc, char *argv[])
Definition: utf8_2.c:35
int try_tds_logout(TDSLOGIN *login, TDSSOCKET *tds, int verbose)
Definition: common.c:128
int try_tds_login(TDSLOGIN **login, TDSSOCKET **tds, const char *appname, int verbose)
Definition: common.c:55
char CHARSET[512]
Definition: common.c:11
static TDSLOGIN * login
Definition: dataread.c:31
static int e2big_count
Definition: utf8_2.c:33
static int einval_count
Definition: utf8_2.c:31
static int eilseq_count
Definition: utf8_2.c:32
static int err_handler(const TDSCONTEXT *tds_ctx, TDSSOCKET *tds, TDSMESSAGE *msg)
Definition: utf8_2.c:176
static char test_name[128]
Definition: utf8_2.c:34
static int eilseq_error
Definition: utf8_2.c:30
static int g_result
Definition: utf8_2.c:28
static TDSSOCKET * tds
Definition: utf8_2.c:27
static int invalid_char
Definition: utf8_2.c:36
static int einval_error
Definition: utf8_2.c:29
static void test(int n, int type)
Definition: utf8_2.c:39
#define tds_submit_query
#define tds_srv_charset_changed
#define tds_process_tokens
#define NULL
Definition: ncbistd.hpp:225
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
exit(2)
char * buf
int i
if(yy_accept[yy_current_state])
yy_size_t n
int strncmp(const char *str1, const char *str2, size_t count)
Definition: odbc_utils.hpp:133
static const char * suffix[]
Definition: pcregrep.c:408
static const char * prefix[]
Definition: pcregrep.c:405
true_type verbose
Definition: processing.cpp:890
Information about blobs (e.g.
Definition: tds.h:658
TDS_CHAR * textvalue
Definition: tds.h:659
Metadata about columns in regular and compute rows.
Definition: tds.h:761
TDSICONV * char_conv
refers to previously allocated iconv information
Definition: tds.h:784
unsigned char * column_data
Definition: tds.h:793
TDS_INT column_cur_size
size written in variable (ie: char, text, binary).
Definition: tds.h:811
TDSICONV ** char_convs
Definition: tds.h:1161
Definition: tds.h:584
TDS_CHAR * message
Definition: tds.h:947
TDSCOLUMN ** columns
Definition: tds.h:844
Information for a server connection.
Definition: tds.h:1211
TDSCONNECTION conn[1]
Definition: tds.h:1215
TDSRESULTINFO * current_results
Current query information.
Definition: tds.h:1263
Definition: type.c:6
Modified on Wed May 22 11:36:58 2024 by modify_doxy.py rev. 669887