~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to lib/misc/codesetBase.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2010 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 * codesetBase.c --
 
21
 *
 
22
 *    Character set and encoding conversion functions, without ICU.
 
23
 */
 
24
 
 
25
#include <stdlib.h>
 
26
#include "vmware.h"
 
27
#include "codeset.h"
 
28
#include "util.h"
 
29
 
 
30
/*
 
31
 *-----------------------------------------------------------------------------
 
32
 *
 
33
 * CodeSet_GetUtf8 --
 
34
 *
 
35
 *      Parse the next UTF-8 sequence.
 
36
 *
 
37
 * Results:
 
38
 *      0 on failure.
 
39
 *      Length of sequence and Unicode character in *uchar on success.
 
40
 *
 
41
 * Side effects:
 
42
 *      None.
 
43
 *
 
44
 *-----------------------------------------------------------------------------
 
45
 */
 
46
 
 
47
int
 
48
CodeSet_GetUtf8(const char *string,  // IN: string
 
49
                const char *end,     // IN: end of string
 
50
                uint32 *uchar)       // OUT: the Unicode character
 
51
{
 
52
   uint8 *p = (uint8 *) string;
 
53
   uint8 *e;
 
54
   uint32 c;
 
55
   int len;
 
56
   ASSERT(string < end);
 
57
 
 
58
   c = *p;
 
59
 
 
60
   if (c < 0x80) {
 
61
      // ASCII: U+0000 - U+007F: 1 byte of UTF-8.
 
62
      len = 1;
 
63
      goto out;
 
64
   }
 
65
 
 
66
   if ((c < 0xc2) || (c > 0xf4)) {
 
67
      // 0x81 to 0xbf are not valid first bytes
 
68
      // 0xc0 and 0xc1 cannot appear in UTF-8, see below
 
69
      // leading char can not be > 0xf4, illegal as well
 
70
      return 0;
 
71
   }
 
72
 
 
73
   if (c < 0xe0) {
 
74
      // U+0080 - U+07FF: 2 bytes of UTF-8.
 
75
      c -= 0xc0;
 
76
      len = 2;
 
77
   } else if (c < 0xf0) {
 
78
      // U+0800 - U+FFFF: 3 bytes of UTF-8.
 
79
      c -= 0xe0;
 
80
      len = 3;
 
81
   } else {
 
82
      // U+10000 - U+10FFFF: 4 bytes of UTF-8.
 
83
      c -= 0xf0;
 
84
      len = 4;
 
85
   }
 
86
 
 
87
   if ((e = p + len) > (uint8 *) end) {
 
88
      // input too short
 
89
      return 0;
 
90
   }
 
91
 
 
92
   while (++p < e) {
 
93
      if ((*p & 0xc0) != 0x80) {
 
94
         // bad trailing byte
 
95
         return 0;
 
96
      }
 
97
      c <<= 6;
 
98
      c += *p - 0x80;
 
99
   }
 
100
 
 
101
   /*
 
102
    * Enforce shortest encoding.
 
103
    * UTF-8 mandates that shortest possible encoding is used,
 
104
    * as otherwise doing UTF-8 => anything => UTF-8 could bypass some
 
105
    * important tests, like '/' for path separator or \0 for string
 
106
    * termination.
 
107
    *
 
108
    * This test does not work for len == 2, but that case is handled
 
109
    * by requiring the first byte to be 0xc2 or greater (see above).
 
110
    */
 
111
 
 
112
   if (c < 1U << (len * 5 - 4)) {
 
113
      return 0;
 
114
   }
 
115
 
 
116
out:
 
117
   if (uchar != NULL) {
 
118
      *uchar = c;
 
119
   }
 
120
 
 
121
   return len;
 
122
}
 
123
 
 
124
 
 
125
/*
 
126
 *-----------------------------------------------------------------------------
 
127
 *
 
128
 * CodeSet_LengthInCodePoints --
 
129
 *
 
130
 *    Return the length of a UTF8 string in code points (the number of
 
131
 *    unicode characters present in the string, not the length of the
 
132
 *    string in bytes).
 
133
 *
 
134
 *    Like strlen, the length returned does not include the terminating NUL.
 
135
 *
 
136
 * Results:
 
137
 *    -1 on error
 
138
 *
 
139
 * Side effects:
 
140
 *    None
 
141
 *
 
142
 *-----------------------------------------------------------------------------
 
143
 */
 
144
 
 
145
int
 
146
CodeSet_LengthInCodePoints(const char *utf8)  // IN:
 
147
{
 
148
   char *p;
 
149
   char *end;
 
150
   uint32 codePoints = 0;
 
151
 
 
152
   ASSERT(utf8);
 
153
 
 
154
   p = (char *) utf8;
 
155
   end = p + strlen(utf8);
 
156
 
 
157
   while (p < end) {
 
158
      uint32 utf32;
 
159
      uint32 len = CodeSet_GetUtf8(p, end, &utf32);
 
160
 
 
161
      if (len == 0) {
 
162
         return -1;
 
163
      }
 
164
 
 
165
      p += len;
 
166
      codePoints++;
 
167
   }
 
168
 
 
169
   return codePoints;
 
170
}
 
171
 
 
172
 
 
173
/*
 
174
 *-----------------------------------------------------------------------------
 
175
 *
 
176
 * CodeSet_UTF8ToUTF32 --
 
177
 *
 
178
 *    Convert a UTF8 string into a UTF32 string. The result is returned as a
 
179
 *    dynamically allocated string that the caller is responsible for.
 
180
 *
 
181
 * Results:
 
182
 *    TRUE   Input string was valid, converted string in *utf32
 
183
 *    FALSE  Input string was invalid or internal error
 
184
 *
 
185
 * Side effects:
 
186
 *    Allocates memory
 
187
 *
 
188
 *-----------------------------------------------------------------------------
 
189
 */
 
190
 
 
191
Bool
 
192
CodeSet_UTF8ToUTF32(const char *utf8,  // IN:
 
193
                    char **utf32)      // OUT:
 
194
{
 
195
   char *p;
 
196
   char *end;
 
197
   uint32 *ptr;
 
198
   int codePoints;
 
199
 
 
200
   ASSERT(utf32);
 
201
 
 
202
   if (utf8 == NULL) {  // NULL is not an error
 
203
      *utf32 = NULL;
 
204
 
 
205
      return TRUE;
 
206
   }
 
207
 
 
208
   codePoints = CodeSet_LengthInCodePoints(utf8);
 
209
   if (codePoints == -1) {
 
210
      *utf32 = NULL;
 
211
 
 
212
      return FALSE;
 
213
   }
 
214
 
 
215
   p = (char *) utf8;
 
216
   end = p + strlen(utf8);
 
217
 
 
218
   ptr = Util_SafeMalloc(sizeof(*ptr) * (codePoints + 1));
 
219
   *utf32 = (char *) ptr;
 
220
 
 
221
   while (p < end) {
 
222
      p += CodeSet_GetUtf8(p, end, ptr++);
 
223
   }
 
224
 
 
225
   *ptr = 0;
 
226
 
 
227
   return TRUE;
 
228
}
 
229
 
 
230
 
 
231
/*
 
232
 *-----------------------------------------------------------------------------
 
233
 *
 
234
 * CodeSet_UTF32ToUTF8 --
 
235
 *
 
236
 *    Convert a UTF32 string into a UTF8 string. The result is returned as a
 
237
 *    dynamically allocated string that the caller is responsible for.
 
238
 *
 
239
 * Results:
 
240
 *    TRUE   Input string was valid, converted string in *utf8
 
241
 *    FALSE  Input string was invalid or internal error
 
242
 *
 
243
 * Side effects:
 
244
 *    Allocates memory
 
245
 *
 
246
 *-----------------------------------------------------------------------------
 
247
 */
 
248
 
 
249
 
 
250
Bool
 
251
CodeSet_UTF32ToUTF8(const char *utf32,  // IN:
 
252
                    char **utf8)        // OUT:
 
253
{
 
254
   uint32 i;
 
255
   uint8 *p;
 
256
   uint8 *q;
 
257
   uint32 len;
 
258
   union {
 
259
      uint32  word;
 
260
      uint8   bytes[4];
 
261
   } value;
 
262
 
 
263
   ASSERT(utf8);
 
264
 
 
265
   if (utf32 == NULL) {  // NULL is not an error
 
266
      *utf8 = NULL;
 
267
 
 
268
      return TRUE;
 
269
   }
 
270
 
 
271
   /*
 
272
    * Determine the length of the UTF32 string. A UTF32 string terminates
 
273
    * with four (4) bytes of zero (0).
 
274
    */
 
275
 
 
276
   len = 0;
 
277
   p = (uint8 *) utf32;
 
278
 
 
279
   while (TRUE) {
 
280
      value.bytes[0] = *p++;
 
281
      value.bytes[1] = *p++;
 
282
      value.bytes[2] = *p++;
 
283
      value.bytes[3] = *p++;
 
284
 
 
285
      if (value.word == 0) {
 
286
         break;
 
287
      }
 
288
 
 
289
      len++;
 
290
   }
 
291
 
 
292
   /*
 
293
    * Now that we know the length, allocate the memory for the UTF8 string.
 
294
    * The UTF8 string length calculation ensures that there will always be
 
295
    * sufficient space to represent the UTF32 string. Most of the time this
 
296
    * will involved allocating too much memory however the memory wastage
 
297
    * will be very short lived and very small.
 
298
    */
 
299
 
 
300
   *utf8 = Util_SafeMalloc((4 * len) + 1);  // cover the NUL byte
 
301
 
 
302
   /*
 
303
    * Process the UTF32 string, converting each code point into its
 
304
    * UTF8 equivalent.
 
305
    */
 
306
 
 
307
   p = (uint8 *) utf32;
 
308
   q = (uint8 *) *utf8;
 
309
 
 
310
   for (i = 0; i < len; i++) {
 
311
      value.bytes[0] = *p++;
 
312
      value.bytes[1] = *p++;
 
313
      value.bytes[2] = *p++;
 
314
      value.bytes[3] = *p++;
 
315
 
 
316
      if (value.word < 0x80) {                      // One byte case (ASCII)
 
317
         *q++ = value.word;
 
318
      } else if (value.word < 0x800) {              // Two byte case
 
319
         *q++ = 0xC0 | (value.word >> 6);
 
320
         *q++ = 0x80 | (value.word & 0x3F);
 
321
      } else if (value.word < 0x10000) {            // Three byte case
 
322
         *q++ = 0xE0 | (value.word >> 12);
 
323
         *q++ = 0x80 | ((value.word >> 6) & 0x3F);
 
324
         *q++ = 0x80 | (value.word & 0x3F);
 
325
      } else if (value.word < 0x110000) {           // Four byte case
 
326
         *q++ = 0xF0 | (value.word >> 18);
 
327
         *q++ = 0x80 | ((value.word >> 12) & 0x3F);
 
328
         *q++ = 0x80 | ((value.word >> 6) & 0x3F);
 
329
         *q++ = 0x80 | (value.word & 0x3F);
 
330
      } else {  // INVALID VALUE!
 
331
         free(*utf8);
 
332
         *utf8 = NULL;
 
333
 
 
334
         return FALSE;
 
335
      }
 
336
   }
 
337
 
 
338
   *q = '\0';
 
339
 
 
340
   return TRUE;
 
341
}
 
342