~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/shared/utf8.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl, Michael Biebl, Michael Stapelberg, Daniel Schaal, Ondrej Balaz
  • Date: 2013-09-12 00:13:11 UTC
  • mfrom: (1.1.11) (9.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 53.
  • Revision ID: package-import@ubuntu.com-20130912001311-dz35it34wr2lbday
Tags: 204-3
[ Michael Biebl ]
* Upload to unstable.
* Use /bin/bash in debug-shell.service as Debian doesn't have /sbin/sushell.
* Only import net.ifaces cmdline property for network devices.
* Generate strict dependencies between the binary packages using a
  shlibs.local file and add an explicit versioned dependency on
  libsystemd-login0 to systemd to ensure packages are upgraded in sync.
  Closes: #719444
* Drop obsolete Replaces: libudev0 from udev package.
* Use correct paths for various binaries, like /sbin/quotaon, which are
  installed in / and not /usr in Debian.  Closes: #721347
* Don't install kernel-install(8) man page since we don't install the
  corresponding binary either.  Closes: #722180
* Cherry-pick upstream fixes to make switching runlevels and starting
  reboot via ctrl-alt-del more robust.
* Cherry-pick upstream fix to properly apply ACLs to Journal files.

[ Michael Stapelberg ]
* Make systemctl enable|disable call update-rc.d for SysV init scripts.
  Closes: #709780
* Don't mount /tmp as tmpfs by default and make it possible to enable this
  feature via "systemctl enable tmp.mount".

[ Daniel Schaal ]
* Add bug-script to systemd and udev.  Closes: #711245

[ Ondrej Balaz ]
* Recognize discard option in /etc/crypttab.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 
2
 
 
3
/***
 
4
  This file is part of systemd.
 
5
 
 
6
  Copyright 2012 Lennart Poettering
 
7
 
 
8
  systemd is free software; you can redistribute it and/or modify it
 
9
  under the terms of the GNU Lesser General Public License as published by
 
10
  the Free Software Foundation; either version 2.1 of the License, or
 
11
  (at your option) any later version.
 
12
 
 
13
  systemd is distributed in the hope that it will be useful, but
 
14
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
16
  Lesser General Public License for more details.
 
17
 
 
18
  You should have received a copy of the GNU Lesser General Public License
 
19
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 
20
***/
 
21
 
 
22
/* This file is based on the GLIB utf8 validation functions. The
 
23
 * original license text follows. */
 
24
 
 
25
/* gutf8.c - Operations on UTF-8 strings.
 
26
 *
 
27
 * Copyright (C) 1999 Tom Tromey
 
28
 * Copyright (C) 2000 Red Hat, Inc.
 
29
 *
 
30
 * This library is free software; you can redistribute it and/or
 
31
 * modify it under the terms of the GNU Library General Public
 
32
 * License as published by the Free Software Foundation; either
 
33
 * version 2 of the License, or (at your option) any later version.
 
34
 *
 
35
 * This library is distributed in the hope that it will be useful,
 
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
38
 * Library General Public License for more details.
 
39
 *
 
40
 * You should have received a copy of the GNU Library General Public
 
41
 * License along with this library; if not, write to the Free Software
 
42
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
43
 */
 
44
 
 
45
#include <errno.h>
 
46
#include <stdlib.h>
 
47
#include <inttypes.h>
 
48
#include <string.h>
 
49
#include <stdbool.h>
 
50
 
 
51
#include "utf8.h"
 
52
#include "util.h"
 
53
 
 
54
#define FILTER_CHAR '_'
 
55
 
 
56
static inline bool is_unicode_valid(uint32_t ch) {
 
57
 
 
58
        if (ch >= 0x110000) /* End of unicode space */
 
59
                return false;
 
60
        if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
 
61
                return false;
 
62
        if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
 
63
                return false;
 
64
        if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
 
65
                return false;
 
66
 
 
67
        return true;
 
68
}
 
69
 
 
70
static inline bool is_continuation_char(uint8_t ch) {
 
71
        if ((ch & 0xc0) != 0x80) /* 10xxxxxx */
 
72
                return false;
 
73
        return true;
 
74
}
 
75
 
 
76
static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) {
 
77
        *u_ch <<= 6;
 
78
        *u_ch |= ch & 0x3f;
 
79
}
 
80
 
 
81
static bool is_unicode_control(uint32_t ch) {
 
82
 
 
83
        /*
 
84
          0 to ' '-1 is the C0 range.
 
85
          DEL=0x7F, and DEL+1 to 0x9F is C1 range.
 
86
          '\t' is in C0 range, but more or less harmless and commonly used.
 
87
        */
 
88
 
 
89
        return (ch < ' ' && ch != '\t') ||
 
90
                (0x7F <= ch && ch <= 0x9F);
 
91
}
 
92
 
 
93
char* utf8_is_printable_n(const char* str, size_t length) {
 
94
        uint32_t val = 0;
 
95
        uint32_t min = 0;
 
96
        const uint8_t *p;
 
97
 
 
98
        assert(str);
 
99
 
 
100
        for (p = (const uint8_t*) str; length; p++, length--) {
 
101
                if (*p < 128) {
 
102
                        val = *p;
 
103
                } else {
 
104
                        if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
 
105
                                min = 128;
 
106
                                val = (uint32_t) (*p & 0x1e);
 
107
                                goto ONE_REMAINING;
 
108
                        } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
 
109
                                min = (1 << 11);
 
110
                                val = (uint32_t) (*p & 0x0f);
 
111
                                goto TWO_REMAINING;
 
112
                        } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
 
113
                                min = (1 << 16);
 
114
                                val = (uint32_t) (*p & 0x07);
 
115
                        } else
 
116
                                goto error;
 
117
 
 
118
                        p++;
 
119
                        length--;
 
120
                        if (!length || !is_continuation_char(*p))
 
121
                                goto error;
 
122
                        merge_continuation_char(&val, *p);
 
123
 
 
124
                TWO_REMAINING:
 
125
                        p++;
 
126
                        length--;
 
127
                        if (!is_continuation_char(*p))
 
128
                                goto error;
 
129
                        merge_continuation_char(&val, *p);
 
130
 
 
131
                ONE_REMAINING:
 
132
                        p++;
 
133
                        length--;
 
134
                        if (!is_continuation_char(*p))
 
135
                                goto error;
 
136
                        merge_continuation_char(&val, *p);
 
137
 
 
138
                        if (val < min)
 
139
                                goto error;
 
140
                }
 
141
 
 
142
                if (is_unicode_control(val))
 
143
                        goto error;
 
144
        }
 
145
 
 
146
        return (char*) str;
 
147
 
 
148
error:
 
149
        return NULL;
 
150
}
 
151
 
 
152
static char* utf8_validate(const char *str, char *output) {
 
153
        uint32_t val = 0;
 
154
        uint32_t min = 0;
 
155
        const uint8_t *p, *last;
 
156
        int size;
 
157
        uint8_t *o;
 
158
 
 
159
        assert(str);
 
160
 
 
161
        o = (uint8_t*) output;
 
162
        for (p = (const uint8_t*) str; *p; p++) {
 
163
                if (*p < 128) {
 
164
                        if (o)
 
165
                                *o = *p;
 
166
                } else {
 
167
                        last = p;
 
168
 
 
169
                        if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
 
170
                                size = 2;
 
171
                                min = 128;
 
172
                                val = (uint32_t) (*p & 0x1e);
 
173
                                goto ONE_REMAINING;
 
174
                        } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
 
175
                                size = 3;
 
176
                                min = (1 << 11);
 
177
                                val = (uint32_t) (*p & 0x0f);
 
178
                                goto TWO_REMAINING;
 
179
                        } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
 
180
                                size = 4;
 
181
                                min = (1 << 16);
 
182
                                val = (uint32_t) (*p & 0x07);
 
183
                        } else
 
184
                                goto error;
 
185
 
 
186
                        p++;
 
187
                        if (!is_continuation_char(*p))
 
188
                                goto error;
 
189
                        merge_continuation_char(&val, *p);
 
190
 
 
191
                TWO_REMAINING:
 
192
                        p++;
 
193
                        if (!is_continuation_char(*p))
 
194
                                goto error;
 
195
                        merge_continuation_char(&val, *p);
 
196
 
 
197
                ONE_REMAINING:
 
198
                        p++;
 
199
                        if (!is_continuation_char(*p))
 
200
                                goto error;
 
201
                        merge_continuation_char(&val, *p);
 
202
 
 
203
                        if (val < min)
 
204
                                goto error;
 
205
 
 
206
                        if (!is_unicode_valid(val))
 
207
                                goto error;
 
208
 
 
209
                        if (o) {
 
210
                                memcpy(o, last, (size_t) size);
 
211
                                o += size;
 
212
                        }
 
213
 
 
214
                        continue;
 
215
 
 
216
                error:
 
217
                        if (o) {
 
218
                                *o = FILTER_CHAR;
 
219
                                p = last; /* We retry at the next character */
 
220
                        } else
 
221
                                goto failure;
 
222
                }
 
223
 
 
224
                if (o)
 
225
                        o++;
 
226
        }
 
227
 
 
228
        if (o) {
 
229
                *o = '\0';
 
230
                return output;
 
231
        }
 
232
 
 
233
        return (char*) str;
 
234
 
 
235
failure:
 
236
        return NULL;
 
237
}
 
238
 
 
239
char* utf8_is_valid (const char *str) {
 
240
        return utf8_validate(str, NULL);
 
241
}
 
242
 
 
243
char* utf8_filter (const char *str) {
 
244
        char *new_str;
 
245
 
 
246
        assert(str);
 
247
 
 
248
        new_str = malloc(strlen(str) + 1);
 
249
        if (!new_str)
 
250
                return NULL;
 
251
 
 
252
        return utf8_validate(str, new_str);
 
253
}
 
254
 
 
255
char *ascii_is_valid(const char *str) {
 
256
        const char *p;
 
257
 
 
258
        assert(str);
 
259
 
 
260
        for (p = str; *p; p++)
 
261
                if ((unsigned char) *p >= 128)
 
262
                        return NULL;
 
263
 
 
264
        return (char*) str;
 
265
}
 
266
 
 
267
char *ascii_filter(const char *str) {
 
268
        const char *s;
 
269
        char *r, *d;
 
270
        size_t l;
 
271
 
 
272
        assert(str);
 
273
 
 
274
        l = strlen(str);
 
275
        r = malloc(l + 1);
 
276
        if (!r)
 
277
                return NULL;
 
278
 
 
279
        for (s = str, d = r; *s; s++)
 
280
                if ((unsigned char) *s < 128)
 
281
                        *(d++) = *s;
 
282
 
 
283
        *d = 0;
 
284
 
 
285
        return r;
 
286
}
 
287
 
 
288
char *utf16_to_utf8(const void *s, size_t length) {
 
289
        char *r;
 
290
        const uint8_t *f;
 
291
        uint8_t *t;
 
292
 
 
293
        r = new(char, (length*3+1)/2 + 1);
 
294
        if (!r)
 
295
                return NULL;
 
296
 
 
297
        t = (uint8_t*) r;
 
298
 
 
299
        for (f = s; f < (const uint8_t*) s + length; f += 2) {
 
300
                uint16_t c;
 
301
 
 
302
                c = (f[1] << 8) | f[0];
 
303
 
 
304
                if (c == 0) {
 
305
                        *t = 0;
 
306
                        return r;
 
307
                } else if (c < 0x80) {
 
308
                        *(t++) = (uint8_t) c;
 
309
                } else if (c < 0x800) {
 
310
                        *(t++) = (uint8_t) (0xc0 | (c >> 6));
 
311
                        *(t++) = (uint8_t) (0x80 | (c & 0x3f));
 
312
                } else {
 
313
                        *(t++) = (uint8_t) (0xe0 | (c >> 12));
 
314
                        *(t++) = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
 
315
                        *(t++) = (uint8_t) (0x80 | (c & 0x3f));
 
316
                }
 
317
        }
 
318
 
 
319
        *t = 0;
 
320
 
 
321
        return r;
 
322
}