~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/utils/mb/mbutils.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file contains public functions for conversion between
 
3
 * client encoding and server (database) encoding.
 
4
 *
 
5
 * Tatsuo Ishii
 
6
 *
 
7
 * src/backend/utils/mb/mbutils.c
 
8
 */
 
9
#include "postgres.h"
 
10
 
 
11
#include "access/xact.h"
 
12
#include "catalog/namespace.h"
 
13
#include "mb/pg_wchar.h"
 
14
#include "utils/builtins.h"
 
15
#include "utils/memutils.h"
 
16
#include "utils/syscache.h"
 
17
 
 
18
/*
 
19
 * When converting strings between different encodings, we assume that space
 
20
 * for converted result is 4-to-1 growth in the worst case. The rate for
 
21
 * currently supported encoding pairs are within 3 (SJIS JIS X0201 half width
 
22
 * kanna -> UTF8 is the worst case).  So "4" should be enough for the moment.
 
23
 *
 
24
 * Note that this is not the same as the maximum character width in any
 
25
 * particular encoding.
 
26
 */
 
27
#define MAX_CONVERSION_GROWTH  4
 
28
 
 
29
/*
 
30
 * We maintain a simple linked list caching the fmgr lookup info for the
 
31
 * currently selected conversion functions, as well as any that have been
 
32
 * selected previously in the current session.  (We remember previous
 
33
 * settings because we must be able to restore a previous setting during
 
34
 * transaction rollback, without doing any fresh catalog accesses.)
 
35
 *
 
36
 * Since we'll never release this data, we just keep it in TopMemoryContext.
 
37
 */
 
38
typedef struct ConvProcInfo
 
39
{
 
40
        int                     s_encoding;             /* server and client encoding IDs */
 
41
        int                     c_encoding;
 
42
        FmgrInfo        to_server_info; /* lookup info for conversion procs */
 
43
        FmgrInfo        to_client_info;
 
44
} ConvProcInfo;
 
45
 
 
46
static List *ConvProcList = NIL;        /* List of ConvProcInfo */
 
47
 
 
48
/*
 
49
 * These variables point to the currently active conversion functions,
 
50
 * or are NULL when no conversion is needed.
 
51
 */
 
52
static FmgrInfo *ToServerConvProc = NULL;
 
53
static FmgrInfo *ToClientConvProc = NULL;
 
54
 
 
55
/*
 
56
 * These variables track the currently selected FE and BE encodings.
 
57
 */
 
58
static pg_enc2name *ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
 
59
static pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
 
60
static pg_enc2name *PlatformEncoding = NULL;
 
61
 
 
62
/*
 
63
 * During backend startup we can't set client encoding because we (a)
 
64
 * can't look up the conversion functions, and (b) may not know the database
 
65
 * encoding yet either.  So SetClientEncoding() just accepts anything and
 
66
 * remembers it for InitializeClientEncoding() to apply later.
 
67
 */
 
68
static bool backend_startup_complete = false;
 
69
static int      pending_client_encoding = PG_SQL_ASCII;
 
70
 
 
71
 
 
72
/* Internal functions */
 
73
static char *perform_default_encoding_conversion(const char *src,
 
74
                                                                        int len, bool is_client_to_server);
 
75
static int      cliplen(const char *str, int len, int limit);
 
76
 
 
77
 
 
78
/*
 
79
 * Prepare for a future call to SetClientEncoding.      Success should mean
 
80
 * that SetClientEncoding is guaranteed to succeed for this encoding request.
 
81
 *
 
82
 * (But note that success before backend_startup_complete does not guarantee
 
83
 * success after ...)
 
84
 *
 
85
 * Returns 0 if okay, -1 if not (bad encoding or can't support conversion)
 
86
 */
 
87
int
 
88
PrepareClientEncoding(int encoding)
 
89
{
 
90
        int                     current_server_encoding;
 
91
        ListCell   *lc;
 
92
 
 
93
        if (!PG_VALID_FE_ENCODING(encoding))
 
94
                return -1;
 
95
 
 
96
        /* Can't do anything during startup, per notes above */
 
97
        if (!backend_startup_complete)
 
98
                return 0;
 
99
 
 
100
        current_server_encoding = GetDatabaseEncoding();
 
101
 
 
102
        /*
 
103
         * Check for cases that require no conversion function.
 
104
         */
 
105
        if (current_server_encoding == encoding ||
 
106
                current_server_encoding == PG_SQL_ASCII ||
 
107
                encoding == PG_SQL_ASCII)
 
108
                return 0;
 
109
 
 
110
        if (IsTransactionState())
 
111
        {
 
112
                /*
 
113
                 * If we're in a live transaction, it's safe to access the catalogs,
 
114
                 * so look up the functions.  We repeat the lookup even if the info is
 
115
                 * already cached, so that we can react to changes in the contents of
 
116
                 * pg_conversion.
 
117
                 */
 
118
                Oid                     to_server_proc,
 
119
                                        to_client_proc;
 
120
                ConvProcInfo *convinfo;
 
121
                MemoryContext oldcontext;
 
122
 
 
123
                to_server_proc = FindDefaultConversionProc(encoding,
 
124
                                                                                                   current_server_encoding);
 
125
                if (!OidIsValid(to_server_proc))
 
126
                        return -1;
 
127
                to_client_proc = FindDefaultConversionProc(current_server_encoding,
 
128
                                                                                                   encoding);
 
129
                if (!OidIsValid(to_client_proc))
 
130
                        return -1;
 
131
 
 
132
                /*
 
133
                 * Load the fmgr info into TopMemoryContext (could still fail here)
 
134
                 */
 
135
                convinfo = (ConvProcInfo *) MemoryContextAlloc(TopMemoryContext,
 
136
                                                                                                           sizeof(ConvProcInfo));
 
137
                convinfo->s_encoding = current_server_encoding;
 
138
                convinfo->c_encoding = encoding;
 
139
                fmgr_info_cxt(to_server_proc, &convinfo->to_server_info,
 
140
                                          TopMemoryContext);
 
141
                fmgr_info_cxt(to_client_proc, &convinfo->to_client_info,
 
142
                                          TopMemoryContext);
 
143
 
 
144
                /* Attach new info to head of list */
 
145
                oldcontext = MemoryContextSwitchTo(TopMemoryContext);
 
146
                ConvProcList = lcons(convinfo, ConvProcList);
 
147
                MemoryContextSwitchTo(oldcontext);
 
148
 
 
149
                /*
 
150
                 * We cannot yet remove any older entry for the same encoding pair,
 
151
                 * since it could still be in use.      SetClientEncoding will clean up.
 
152
                 */
 
153
 
 
154
                return 0;                               /* success */
 
155
        }
 
156
        else
 
157
        {
 
158
                /*
 
159
                 * If we're not in a live transaction, the only thing we can do is
 
160
                 * restore a previous setting using the cache.  This covers all
 
161
                 * transaction-rollback cases.  The only case it might not work for is
 
162
                 * trying to change client_encoding on the fly by editing
 
163
                 * postgresql.conf and SIGHUP'ing.  Which would probably be a stupid
 
164
                 * thing to do anyway.
 
165
                 */
 
166
                foreach(lc, ConvProcList)
 
167
                {
 
168
                        ConvProcInfo *oldinfo = (ConvProcInfo *) lfirst(lc);
 
169
 
 
170
                        if (oldinfo->s_encoding == current_server_encoding &&
 
171
                                oldinfo->c_encoding == encoding)
 
172
                                return 0;
 
173
                }
 
174
 
 
175
                return -1;                              /* it's not cached, so fail */
 
176
        }
 
177
}
 
178
 
 
179
/*
 
180
 * Set the active client encoding and set up the conversion-function pointers.
 
181
 * PrepareClientEncoding should have been called previously for this encoding.
 
182
 *
 
183
 * Returns 0 if okay, -1 if not (bad encoding or can't support conversion)
 
184
 */
 
185
int
 
186
SetClientEncoding(int encoding)
 
187
{
 
188
        int                     current_server_encoding;
 
189
        bool            found;
 
190
        ListCell   *lc;
 
191
        ListCell   *prev;
 
192
        ListCell   *next;
 
193
 
 
194
        if (!PG_VALID_FE_ENCODING(encoding))
 
195
                return -1;
 
196
 
 
197
        /* Can't do anything during startup, per notes above */
 
198
        if (!backend_startup_complete)
 
199
        {
 
200
                pending_client_encoding = encoding;
 
201
                return 0;
 
202
        }
 
203
 
 
204
        current_server_encoding = GetDatabaseEncoding();
 
205
 
 
206
        /*
 
207
         * Check for cases that require no conversion function.
 
208
         */
 
209
        if (current_server_encoding == encoding ||
 
210
                current_server_encoding == PG_SQL_ASCII ||
 
211
                encoding == PG_SQL_ASCII)
 
212
        {
 
213
                ClientEncoding = &pg_enc2name_tbl[encoding];
 
214
                ToServerConvProc = NULL;
 
215
                ToClientConvProc = NULL;
 
216
                return 0;
 
217
        }
 
218
 
 
219
        /*
 
220
         * Search the cache for the entry previously prepared by
 
221
         * PrepareClientEncoding; if there isn't one, we lose.  While at it,
 
222
         * release any duplicate entries so that repeated Prepare/Set cycles don't
 
223
         * leak memory.
 
224
         */
 
225
        found = false;
 
226
        prev = NULL;
 
227
        for (lc = list_head(ConvProcList); lc; lc = next)
 
228
        {
 
229
                ConvProcInfo *convinfo = (ConvProcInfo *) lfirst(lc);
 
230
 
 
231
                next = lnext(lc);
 
232
 
 
233
                if (convinfo->s_encoding == current_server_encoding &&
 
234
                        convinfo->c_encoding == encoding)
 
235
                {
 
236
                        if (!found)
 
237
                        {
 
238
                                /* Found newest entry, so set up */
 
239
                                ClientEncoding = &pg_enc2name_tbl[encoding];
 
240
                                ToServerConvProc = &convinfo->to_server_info;
 
241
                                ToClientConvProc = &convinfo->to_client_info;
 
242
                                found = true;
 
243
                        }
 
244
                        else
 
245
                        {
 
246
                                /* Duplicate entry, release it */
 
247
                                ConvProcList = list_delete_cell(ConvProcList, lc, prev);
 
248
                                pfree(convinfo);
 
249
                                continue;               /* prev mustn't advance */
 
250
                        }
 
251
                }
 
252
 
 
253
                prev = lc;
 
254
        }
 
255
 
 
256
        if (found)
 
257
                return 0;                               /* success */
 
258
        else
 
259
                return -1;                              /* it's not cached, so fail */
 
260
}
 
261
 
 
262
/*
 
263
 * Initialize client encoding conversions.
 
264
 *              Called from InitPostgres() once during backend startup.
 
265
 */
 
266
void
 
267
InitializeClientEncoding(void)
 
268
{
 
269
        Assert(!backend_startup_complete);
 
270
        backend_startup_complete = true;
 
271
 
 
272
        if (PrepareClientEncoding(pending_client_encoding) < 0 ||
 
273
                SetClientEncoding(pending_client_encoding) < 0)
 
274
        {
 
275
                /*
 
276
                 * Oops, the requested conversion is not available. We couldn't fail
 
277
                 * before, but we can now.
 
278
                 */
 
279
                ereport(FATAL,
 
280
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 
281
                                 errmsg("conversion between %s and %s is not supported",
 
282
                                                pg_enc2name_tbl[pending_client_encoding].name,
 
283
                                                GetDatabaseEncodingName())));
 
284
        }
 
285
}
 
286
 
 
287
/*
 
288
 * returns the current client encoding
 
289
 */
 
290
int
 
291
pg_get_client_encoding(void)
 
292
{
 
293
        Assert(ClientEncoding);
 
294
        return ClientEncoding->encoding;
 
295
}
 
296
 
 
297
/*
 
298
 * returns the current client encoding name
 
299
 */
 
300
const char *
 
301
pg_get_client_encoding_name(void)
 
302
{
 
303
        Assert(ClientEncoding);
 
304
        return ClientEncoding->name;
 
305
}
 
306
 
 
307
/*
 
308
 * Apply encoding conversion on src and return it. The encoding
 
309
 * conversion function is chosen from the pg_conversion system catalog
 
310
 * marked as "default". If it is not found in the schema search path,
 
311
 * it's taken from pg_catalog schema. If it even is not in the schema,
 
312
 * warn and return src.
 
313
 *
 
314
 * If conversion occurs, a palloc'd null-terminated string is returned.
 
315
 * In the case of no conversion, src is returned.
 
316
 *
 
317
 * CAUTION: although the presence of a length argument means that callers
 
318
 * can pass non-null-terminated strings, care is required because the same
 
319
 * string will be passed back if no conversion occurs.  Such callers *must*
 
320
 * check whether result == src and handle that case differently.
 
321
 *
 
322
 * Note: we try to avoid raising error, since that could get us into
 
323
 * infinite recursion when this function is invoked during error message
 
324
 * sending.  It should be OK to raise error for overlength strings though,
 
325
 * since the recursion will come with a shorter message.
 
326
 */
 
327
unsigned char *
 
328
pg_do_encoding_conversion(unsigned char *src, int len,
 
329
                                                  int src_encoding, int dest_encoding)
 
330
{
 
331
        unsigned char *result;
 
332
        Oid                     proc;
 
333
 
 
334
        if (!IsTransactionState())
 
335
                return src;
 
336
 
 
337
        if (src_encoding == dest_encoding)
 
338
                return src;
 
339
 
 
340
        if (src_encoding == PG_SQL_ASCII || dest_encoding == PG_SQL_ASCII)
 
341
                return src;
 
342
 
 
343
        if (len <= 0)
 
344
                return src;
 
345
 
 
346
        proc = FindDefaultConversionProc(src_encoding, dest_encoding);
 
347
        if (!OidIsValid(proc))
 
348
        {
 
349
                ereport(LOG,
 
350
                                (errcode(ERRCODE_UNDEFINED_FUNCTION),
 
351
                                 errmsg("default conversion function for encoding \"%s\" to \"%s\" does not exist",
 
352
                                                pg_encoding_to_char(src_encoding),
 
353
                                                pg_encoding_to_char(dest_encoding))));
 
354
                return src;
 
355
        }
 
356
 
 
357
        /*
 
358
         * XXX we should avoid throwing errors in OidFunctionCall. Otherwise we
 
359
         * are going into infinite loop!  So we have to make sure that the
 
360
         * function exists before calling OidFunctionCall.
 
361
         */
 
362
        if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(proc)))
 
363
        {
 
364
                elog(LOG, "cache lookup failed for function %u", proc);
 
365
                return src;
 
366
        }
 
367
 
 
368
        /*
 
369
         * Allocate space for conversion result, being wary of integer overflow
 
370
         */
 
371
        if ((Size) len >= (MaxAllocSize / (Size) MAX_CONVERSION_GROWTH))
 
372
                ereport(ERROR,
 
373
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 
374
                                 errmsg("out of memory"),
 
375
                 errdetail("String of %d bytes is too long for encoding conversion.",
 
376
                                   len)));
 
377
 
 
378
        result = palloc(len * MAX_CONVERSION_GROWTH + 1);
 
379
 
 
380
        OidFunctionCall5(proc,
 
381
                                         Int32GetDatum(src_encoding),
 
382
                                         Int32GetDatum(dest_encoding),
 
383
                                         CStringGetDatum(src),
 
384
                                         CStringGetDatum(result),
 
385
                                         Int32GetDatum(len));
 
386
        return result;
 
387
}
 
388
 
 
389
/*
 
390
 * Convert string using encoding_name. The source
 
391
 * encoding is the DB encoding.
 
392
 *
 
393
 * BYTEA convert_to(TEXT string, NAME encoding_name) */
 
394
Datum
 
395
pg_convert_to(PG_FUNCTION_ARGS)
 
396
{
 
397
        Datum           string = PG_GETARG_DATUM(0);
 
398
        Datum           dest_encoding_name = PG_GETARG_DATUM(1);
 
399
        Datum           src_encoding_name = DirectFunctionCall1(namein,
 
400
                                                                        CStringGetDatum(DatabaseEncoding->name));
 
401
        Datum           result;
 
402
 
 
403
        /*
 
404
         * pg_convert expects a bytea as its first argument. We're passing it a
 
405
         * text argument here, relying on the fact that they are both in fact
 
406
         * varlena types, and thus structurally identical.
 
407
         */
 
408
        result = DirectFunctionCall3(pg_convert, string,
 
409
                                                                 src_encoding_name, dest_encoding_name);
 
410
 
 
411
        PG_RETURN_DATUM(result);
 
412
}
 
413
 
 
414
/*
 
415
 * Convert string using encoding_name. The destination
 
416
 * encoding is the DB encoding.
 
417
 *
 
418
 * TEXT convert_from(BYTEA string, NAME encoding_name) */
 
419
Datum
 
420
pg_convert_from(PG_FUNCTION_ARGS)
 
421
{
 
422
        Datum           string = PG_GETARG_DATUM(0);
 
423
        Datum           src_encoding_name = PG_GETARG_DATUM(1);
 
424
        Datum           dest_encoding_name = DirectFunctionCall1(namein,
 
425
                                                                        CStringGetDatum(DatabaseEncoding->name));
 
426
        Datum           result;
 
427
 
 
428
        result = DirectFunctionCall3(pg_convert, string,
 
429
                                                                 src_encoding_name, dest_encoding_name);
 
430
 
 
431
        /*
 
432
         * pg_convert returns a bytea, which we in turn return as text, relying on
 
433
         * the fact that they are both in fact varlena types, and thus
 
434
         * structurally identical. Although not all bytea values are valid text,
 
435
         * in this case it will be because we've told pg_convert to return one
 
436
         * that is valid as text in the current database encoding.
 
437
         */
 
438
        PG_RETURN_DATUM(result);
 
439
}
 
440
 
 
441
/*
 
442
 * Convert string using encoding_names.
 
443
 *
 
444
 * BYTEA convert(BYTEA string, NAME src_encoding_name, NAME dest_encoding_name)
 
445
 */
 
446
Datum
 
447
pg_convert(PG_FUNCTION_ARGS)
 
448
{
 
449
        bytea      *string = PG_GETARG_BYTEA_PP(0);
 
450
        char       *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
 
451
        int                     src_encoding = pg_char_to_encoding(src_encoding_name);
 
452
        char       *dest_encoding_name = NameStr(*PG_GETARG_NAME(2));
 
453
        int                     dest_encoding = pg_char_to_encoding(dest_encoding_name);
 
454
        const char *src_str;
 
455
        char       *dest_str;
 
456
        bytea      *retval;
 
457
        int                     len;
 
458
 
 
459
        if (src_encoding < 0)
 
460
                ereport(ERROR,
 
461
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
462
                                 errmsg("invalid source encoding name \"%s\"",
 
463
                                                src_encoding_name)));
 
464
        if (dest_encoding < 0)
 
465
                ereport(ERROR,
 
466
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
467
                                 errmsg("invalid destination encoding name \"%s\"",
 
468
                                                dest_encoding_name)));
 
469
 
 
470
        /* make sure that source string is valid */
 
471
        len = VARSIZE_ANY_EXHDR(string);
 
472
        src_str = VARDATA_ANY(string);
 
473
        pg_verify_mbstr_len(src_encoding, src_str, len, false);
 
474
 
 
475
        dest_str = (char *) pg_do_encoding_conversion(
 
476
                                (unsigned char *) src_str, len, src_encoding, dest_encoding);
 
477
        if (dest_str != src_str)
 
478
                len = strlen(dest_str);
 
479
 
 
480
        /*
 
481
         * build bytea data type structure.
 
482
         */
 
483
        retval = (bytea *) palloc(len + VARHDRSZ);
 
484
        SET_VARSIZE(retval, len + VARHDRSZ);
 
485
        memcpy(VARDATA(retval), dest_str, len);
 
486
 
 
487
        if (dest_str != src_str)
 
488
                pfree(dest_str);
 
489
 
 
490
        /* free memory if allocated by the toaster */
 
491
        PG_FREE_IF_COPY(string, 0);
 
492
 
 
493
        PG_RETURN_BYTEA_P(retval);
 
494
}
 
495
 
 
496
/*
 
497
 * get the length of the string considered as text in the specified
 
498
 * encoding. Raises an error if the data is not valid in that
 
499
 * encoding.
 
500
 *
 
501
 * INT4 length (BYTEA string, NAME src_encoding_name)
 
502
 */
 
503
Datum
 
504
length_in_encoding(PG_FUNCTION_ARGS)
 
505
{
 
506
        bytea      *string = PG_GETARG_BYTEA_P(0);
 
507
        char       *src_encoding_name = NameStr(*PG_GETARG_NAME(1));
 
508
        int                     src_encoding = pg_char_to_encoding(src_encoding_name);
 
509
        int                     len = VARSIZE(string) - VARHDRSZ;
 
510
        int                     retval;
 
511
 
 
512
        if (src_encoding < 0)
 
513
                ereport(ERROR,
 
514
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
515
                                 errmsg("invalid encoding name \"%s\"",
 
516
                                                src_encoding_name)));
 
517
 
 
518
        retval = pg_verify_mbstr_len(src_encoding, VARDATA(string), len, false);
 
519
        PG_RETURN_INT32(retval);
 
520
 
 
521
}
 
522
 
 
523
Datum
 
524
pg_encoding_max_length_sql(PG_FUNCTION_ARGS)
 
525
{
 
526
        int                     encoding = PG_GETARG_INT32(0);
 
527
 
 
528
        if (PG_VALID_ENCODING(encoding))
 
529
                PG_RETURN_INT32(pg_wchar_table[encoding].maxmblen);
 
530
        else
 
531
                PG_RETURN_NULL();
 
532
}
 
533
 
 
534
/*
 
535
 * convert client encoding to server encoding.
 
536
 */
 
537
char *
 
538
pg_client_to_server(const char *s, int len)
 
539
{
 
540
        Assert(ClientEncoding);
 
541
 
 
542
        return pg_any_to_server(s, len, ClientEncoding->encoding);
 
543
}
 
544
 
 
545
/*
 
546
 * convert any encoding to server encoding.
 
547
 */
 
548
char *
 
549
pg_any_to_server(const char *s, int len, int encoding)
 
550
{
 
551
        Assert(DatabaseEncoding);
 
552
        Assert(ClientEncoding);
 
553
 
 
554
        if (len <= 0)
 
555
                return (char *) s;
 
556
 
 
557
        if (encoding == DatabaseEncoding->encoding ||
 
558
                encoding == PG_SQL_ASCII)
 
559
        {
 
560
                /*
 
561
                 * No conversion is needed, but we must still validate the data.
 
562
                 */
 
563
                (void) pg_verify_mbstr(DatabaseEncoding->encoding, s, len, false);
 
564
                return (char *) s;
 
565
        }
 
566
 
 
567
        if (DatabaseEncoding->encoding == PG_SQL_ASCII)
 
568
        {
 
569
                /*
 
570
                 * No conversion is possible, but we must still validate the data,
 
571
                 * because the client-side code might have done string escaping using
 
572
                 * the selected client_encoding.  If the client encoding is ASCII-safe
 
573
                 * then we just do a straight validation under that encoding.  For an
 
574
                 * ASCII-unsafe encoding we have a problem: we dare not pass such data
 
575
                 * to the parser but we have no way to convert it.      We compromise by
 
576
                 * rejecting the data if it contains any non-ASCII characters.
 
577
                 */
 
578
                if (PG_VALID_BE_ENCODING(encoding))
 
579
                        (void) pg_verify_mbstr(encoding, s, len, false);
 
580
                else
 
581
                {
 
582
                        int                     i;
 
583
 
 
584
                        for (i = 0; i < len; i++)
 
585
                        {
 
586
                                if (s[i] == '\0' || IS_HIGHBIT_SET(s[i]))
 
587
                                        ereport(ERROR,
 
588
                                                        (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
 
589
                                         errmsg("invalid byte value for encoding \"%s\": 0x%02x",
 
590
                                                        pg_enc2name_tbl[PG_SQL_ASCII].name,
 
591
                                                        (unsigned char) s[i])));
 
592
                        }
 
593
                }
 
594
                return (char *) s;
 
595
        }
 
596
 
 
597
        if (ClientEncoding->encoding == encoding)
 
598
                return perform_default_encoding_conversion(s, len, true);
 
599
        else
 
600
                return (char *) pg_do_encoding_conversion(
 
601
                         (unsigned char *) s, len, encoding, DatabaseEncoding->encoding);
 
602
}
 
603
 
 
604
/*
 
605
 * convert server encoding to client encoding.
 
606
 */
 
607
char *
 
608
pg_server_to_client(const char *s, int len)
 
609
{
 
610
        Assert(ClientEncoding);
 
611
 
 
612
        return pg_server_to_any(s, len, ClientEncoding->encoding);
 
613
}
 
614
 
 
615
/*
 
616
 * convert server encoding to any encoding.
 
617
 */
 
618
char *
 
619
pg_server_to_any(const char *s, int len, int encoding)
 
620
{
 
621
        Assert(DatabaseEncoding);
 
622
        Assert(ClientEncoding);
 
623
 
 
624
        if (len <= 0)
 
625
                return (char *) s;
 
626
 
 
627
        if (encoding == DatabaseEncoding->encoding ||
 
628
                encoding == PG_SQL_ASCII ||
 
629
                DatabaseEncoding->encoding == PG_SQL_ASCII)
 
630
                return (char *) s;              /* assume data is valid */
 
631
 
 
632
        if (ClientEncoding->encoding == encoding)
 
633
                return perform_default_encoding_conversion(s, len, false);
 
634
        else
 
635
                return (char *) pg_do_encoding_conversion(
 
636
                         (unsigned char *) s, len, DatabaseEncoding->encoding, encoding);
 
637
}
 
638
 
 
639
/*
 
640
 *      Perform default encoding conversion using cached FmgrInfo. Since
 
641
 *      this function does not access database at all, it is safe to call
 
642
 *      outside transactions.  If the conversion has not been set up by
 
643
 *      SetClientEncoding(), no conversion is performed.
 
644
 */
 
645
static char *
 
646
perform_default_encoding_conversion(const char *src, int len, bool is_client_to_server)
 
647
{
 
648
        char       *result;
 
649
        int                     src_encoding,
 
650
                                dest_encoding;
 
651
        FmgrInfo   *flinfo;
 
652
 
 
653
        if (is_client_to_server)
 
654
        {
 
655
                src_encoding = ClientEncoding->encoding;
 
656
                dest_encoding = DatabaseEncoding->encoding;
 
657
                flinfo = ToServerConvProc;
 
658
        }
 
659
        else
 
660
        {
 
661
                src_encoding = DatabaseEncoding->encoding;
 
662
                dest_encoding = ClientEncoding->encoding;
 
663
                flinfo = ToClientConvProc;
 
664
        }
 
665
 
 
666
        if (flinfo == NULL)
 
667
                return (char *) src;
 
668
 
 
669
        /*
 
670
         * Allocate space for conversion result, being wary of integer overflow
 
671
         */
 
672
        if ((Size) len >= (MaxAllocSize / (Size) MAX_CONVERSION_GROWTH))
 
673
                ereport(ERROR,
 
674
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 
675
                                 errmsg("out of memory"),
 
676
                 errdetail("String of %d bytes is too long for encoding conversion.",
 
677
                                   len)));
 
678
 
 
679
        result = palloc(len * MAX_CONVERSION_GROWTH + 1);
 
680
 
 
681
        FunctionCall5(flinfo,
 
682
                                  Int32GetDatum(src_encoding),
 
683
                                  Int32GetDatum(dest_encoding),
 
684
                                  CStringGetDatum(src),
 
685
                                  CStringGetDatum(result),
 
686
                                  Int32GetDatum(len));
 
687
        return result;
 
688
}
 
689
 
 
690
 
 
691
/* convert a multibyte string to a wchar */
 
692
int
 
693
pg_mb2wchar(const char *from, pg_wchar *to)
 
694
{
 
695
        return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, strlen(from));
 
696
}
 
697
 
 
698
/* convert a multibyte string to a wchar with a limited length */
 
699
int
 
700
pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
 
701
{
 
702
        return (*pg_wchar_table[DatabaseEncoding->encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len);
 
703
}
 
704
 
 
705
/* same, with any encoding */
 
706
int
 
707
pg_encoding_mb2wchar_with_len(int encoding,
 
708
                                                          const char *from, pg_wchar *to, int len)
 
709
{
 
710
        return (*pg_wchar_table[encoding].mb2wchar_with_len) ((const unsigned char *) from, to, len);
 
711
}
 
712
 
 
713
/* returns the byte length of a multibyte character */
 
714
int
 
715
pg_mblen(const char *mbstr)
 
716
{
 
717
        return ((*pg_wchar_table[DatabaseEncoding->encoding].mblen) ((const unsigned char *) mbstr));
 
718
}
 
719
 
 
720
/* returns the display length of a multibyte character */
 
721
int
 
722
pg_dsplen(const char *mbstr)
 
723
{
 
724
        return ((*pg_wchar_table[DatabaseEncoding->encoding].dsplen) ((const unsigned char *) mbstr));
 
725
}
 
726
 
 
727
/* returns the length (counted in wchars) of a multibyte string */
 
728
int
 
729
pg_mbstrlen(const char *mbstr)
 
730
{
 
731
        int                     len = 0;
 
732
 
 
733
        /* optimization for single byte encoding */
 
734
        if (pg_database_encoding_max_length() == 1)
 
735
                return strlen(mbstr);
 
736
 
 
737
        while (*mbstr)
 
738
        {
 
739
                mbstr += pg_mblen(mbstr);
 
740
                len++;
 
741
        }
 
742
        return len;
 
743
}
 
744
 
 
745
/* returns the length (counted in wchars) of a multibyte string
 
746
 * (not necessarily NULL terminated)
 
747
 */
 
748
int
 
749
pg_mbstrlen_with_len(const char *mbstr, int limit)
 
750
{
 
751
        int                     len = 0;
 
752
 
 
753
        /* optimization for single byte encoding */
 
754
        if (pg_database_encoding_max_length() == 1)
 
755
                return limit;
 
756
 
 
757
        while (limit > 0 && *mbstr)
 
758
        {
 
759
                int                     l = pg_mblen(mbstr);
 
760
 
 
761
                limit -= l;
 
762
                mbstr += l;
 
763
                len++;
 
764
        }
 
765
        return len;
 
766
}
 
767
 
 
768
/*
 
769
 * returns the byte length of a multibyte string
 
770
 * (not necessarily NULL terminated)
 
771
 * that is no longer than limit.
 
772
 * this function does not break multibyte character boundary.
 
773
 */
 
774
int
 
775
pg_mbcliplen(const char *mbstr, int len, int limit)
 
776
{
 
777
        return pg_encoding_mbcliplen(DatabaseEncoding->encoding, mbstr,
 
778
                                                                 len, limit);
 
779
}
 
780
 
 
781
/*
 
782
 * pg_mbcliplen with specified encoding
 
783
 */
 
784
int
 
785
pg_encoding_mbcliplen(int encoding, const char *mbstr,
 
786
                                          int len, int limit)
 
787
{
 
788
        mblen_converter mblen_fn;
 
789
        int                     clen = 0;
 
790
        int                     l;
 
791
 
 
792
        /* optimization for single byte encoding */
 
793
        if (pg_encoding_max_length(encoding) == 1)
 
794
                return cliplen(mbstr, len, limit);
 
795
 
 
796
        mblen_fn = pg_wchar_table[encoding].mblen;
 
797
 
 
798
        while (len > 0 && *mbstr)
 
799
        {
 
800
                l = (*mblen_fn) ((const unsigned char *) mbstr);
 
801
                if ((clen + l) > limit)
 
802
                        break;
 
803
                clen += l;
 
804
                if (clen == limit)
 
805
                        break;
 
806
                len -= l;
 
807
                mbstr += l;
 
808
        }
 
809
        return clen;
 
810
}
 
811
 
 
812
/*
 
813
 * Similar to pg_mbcliplen except the limit parameter specifies the
 
814
 * character length, not the byte length.
 
815
 */
 
816
int
 
817
pg_mbcharcliplen(const char *mbstr, int len, int limit)
 
818
{
 
819
        int                     clen = 0;
 
820
        int                     nch = 0;
 
821
        int                     l;
 
822
 
 
823
        /* optimization for single byte encoding */
 
824
        if (pg_database_encoding_max_length() == 1)
 
825
                return cliplen(mbstr, len, limit);
 
826
 
 
827
        while (len > 0 && *mbstr)
 
828
        {
 
829
                l = pg_mblen(mbstr);
 
830
                nch++;
 
831
                if (nch > limit)
 
832
                        break;
 
833
                clen += l;
 
834
                len -= l;
 
835
                mbstr += l;
 
836
        }
 
837
        return clen;
 
838
}
 
839
 
 
840
/* mbcliplen for any single-byte encoding */
 
841
static int
 
842
cliplen(const char *str, int len, int limit)
 
843
{
 
844
        int                     l = 0;
 
845
 
 
846
        len = Min(len, limit);
 
847
        while (l < len && str[l])
 
848
                l++;
 
849
        return l;
 
850
}
 
851
 
 
852
void
 
853
SetDatabaseEncoding(int encoding)
 
854
{
 
855
        if (!PG_VALID_BE_ENCODING(encoding))
 
856
                elog(ERROR, "invalid database encoding: %d", encoding);
 
857
 
 
858
        DatabaseEncoding = &pg_enc2name_tbl[encoding];
 
859
        Assert(DatabaseEncoding->encoding == encoding);
 
860
}
 
861
 
 
862
/*
 
863
 * Bind gettext to the codeset equivalent with the database encoding.
 
864
 */
 
865
void
 
866
pg_bind_textdomain_codeset(const char *domainname)
 
867
{
 
868
#if defined(ENABLE_NLS)
 
869
        int                     encoding = GetDatabaseEncoding();
 
870
        int                     i;
 
871
 
 
872
        /*
 
873
         * gettext() uses the codeset specified by LC_CTYPE by default, so if that
 
874
         * matches the database encoding we don't need to do anything. In CREATE
 
875
         * DATABASE, we enforce or trust that the locale's codeset matches
 
876
         * database encoding, except for the C locale. In C locale, we bind
 
877
         * gettext() explicitly to the right codeset.
 
878
         *
 
879
         * On Windows, though, gettext() tends to get confused so we always bind
 
880
         * it.
 
881
         */
 
882
#ifndef WIN32
 
883
        const char *ctype = setlocale(LC_CTYPE, NULL);
 
884
 
 
885
        if (pg_strcasecmp(ctype, "C") != 0 && pg_strcasecmp(ctype, "POSIX") != 0)
 
886
                return;
 
887
#endif
 
888
 
 
889
        for (i = 0; pg_enc2gettext_tbl[i].name != NULL; i++)
 
890
        {
 
891
                if (pg_enc2gettext_tbl[i].encoding == encoding)
 
892
                {
 
893
                        if (bind_textdomain_codeset(domainname,
 
894
                                                                                pg_enc2gettext_tbl[i].name) == NULL)
 
895
                                elog(LOG, "bind_textdomain_codeset failed");
 
896
                        break;
 
897
                }
 
898
        }
 
899
#endif
 
900
}
 
901
 
 
902
int
 
903
GetDatabaseEncoding(void)
 
904
{
 
905
        Assert(DatabaseEncoding);
 
906
        return DatabaseEncoding->encoding;
 
907
}
 
908
 
 
909
const char *
 
910
GetDatabaseEncodingName(void)
 
911
{
 
912
        Assert(DatabaseEncoding);
 
913
        return DatabaseEncoding->name;
 
914
}
 
915
 
 
916
Datum
 
917
getdatabaseencoding(PG_FUNCTION_ARGS)
 
918
{
 
919
        Assert(DatabaseEncoding);
 
920
        return DirectFunctionCall1(namein, CStringGetDatum(DatabaseEncoding->name));
 
921
}
 
922
 
 
923
Datum
 
924
pg_client_encoding(PG_FUNCTION_ARGS)
 
925
{
 
926
        Assert(ClientEncoding);
 
927
        return DirectFunctionCall1(namein, CStringGetDatum(ClientEncoding->name));
 
928
}
 
929
 
 
930
int
 
931
GetPlatformEncoding(void)
 
932
{
 
933
        if (PlatformEncoding == NULL)
 
934
        {
 
935
                /* try to determine encoding of server's environment locale */
 
936
                int                     encoding = pg_get_encoding_from_locale("", true);
 
937
 
 
938
                if (encoding < 0)
 
939
                        encoding = PG_SQL_ASCII;
 
940
                PlatformEncoding = &pg_enc2name_tbl[encoding];
 
941
        }
 
942
        return PlatformEncoding->encoding;
 
943
}
 
944
 
 
945
#ifdef WIN32
 
946
 
 
947
/*
 
948
 * Result is palloc'ed null-terminated utf16 string. The character length
 
949
 * is also passed to utf16len if not null. Returns NULL iff failed.
 
950
 */
 
951
WCHAR *
 
952
pgwin32_toUTF16(const char *str, int len, int *utf16len)
 
953
{
 
954
        WCHAR      *utf16;
 
955
        int                     dstlen;
 
956
        UINT            codepage;
 
957
 
 
958
        codepage = pg_enc2name_tbl[GetDatabaseEncoding()].codepage;
 
959
 
 
960
        /*
 
961
         * Use MultiByteToWideChar directly if there is a corresponding codepage,
 
962
         * or double conversion through UTF8 if not.
 
963
         */
 
964
        if (codepage != 0)
 
965
        {
 
966
                utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
 
967
                dstlen = MultiByteToWideChar(codepage, 0, str, len, utf16, len);
 
968
                utf16[dstlen] = (WCHAR) 0;
 
969
        }
 
970
        else
 
971
        {
 
972
                char       *utf8;
 
973
 
 
974
                utf8 = (char *) pg_do_encoding_conversion((unsigned char *) str,
 
975
                                                                                len, GetDatabaseEncoding(), PG_UTF8);
 
976
                if (utf8 != str)
 
977
                        len = strlen(utf8);
 
978
 
 
979
                utf16 = (WCHAR *) palloc(sizeof(WCHAR) * (len + 1));
 
980
                dstlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, len);
 
981
                utf16[dstlen] = (WCHAR) 0;
 
982
 
 
983
                if (utf8 != str)
 
984
                        pfree(utf8);
 
985
        }
 
986
 
 
987
        if (dstlen == 0 && len > 0)
 
988
        {
 
989
                pfree(utf16);
 
990
                return NULL;                    /* error */
 
991
        }
 
992
 
 
993
        if (utf16len)
 
994
                *utf16len = dstlen;
 
995
        return utf16;
 
996
}
 
997
 
 
998
#endif