1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4
This file is part of systemd.
6
Copyright 2012 Lennart Poettering
8
systemd is free software; you can redistribute it and/or modify it
9
under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
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
General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with systemd; If not, see <http://www.gnu.org/licenses/>.
22
/* This file is based on the GLIB utf8 validation functions. The
23
* original license text follows. */
25
/* gutf8.c - Operations on UTF-8 strings.
27
* Copyright (C) 1999 Tom Tromey
28
* Copyright (C) 2000 Red Hat, Inc.
30
* This library is free software; you can redistribute it and/or
31
* modify it under the terms of the GNU Lesser 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.
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
* Lesser General Public License for more details.
40
* You should have received a copy of the GNU Lesser General Public
41
* License along with this library; if not, write to the
42
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43
* Boston, MA 02111-1307, USA.
54
#define FILTER_CHAR '_'
56
static inline bool is_unicode_valid(uint32_t ch) {
58
if (ch >= 0x110000) /* End of unicode space */
60
if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
62
if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
64
if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
70
static inline bool is_continuation_char(uint8_t ch) {
71
if ((ch & 0xc0) != 0x80) /* 10xxxxxx */
76
static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) {
81
static char* utf8_validate(const char *str, char *output) {
84
const uint8_t *p, *last;
90
o = (uint8_t*) output;
91
for (p = (const uint8_t*) str; *p; p++) {
98
if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
101
val = (uint32_t) (*p & 0x1e);
103
} else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
106
val = (uint32_t) (*p & 0x0f);
108
} else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
111
val = (uint32_t) (*p & 0x07);
116
if (!is_continuation_char(*p))
118
merge_continuation_char(&val, *p);
122
if (!is_continuation_char(*p))
124
merge_continuation_char(&val, *p);
128
if (!is_continuation_char(*p))
130
merge_continuation_char(&val, *p);
135
if (!is_unicode_valid(val))
139
memcpy(o, last, (size_t) size);
148
p = last; /* We retry at the next character */
168
char* utf8_is_valid (const char *str) {
169
return utf8_validate(str, NULL);
172
char* utf8_filter (const char *str) {
177
new_str = malloc(strlen(str) + 1);
181
return utf8_validate(str, new_str);
184
char *ascii_is_valid(const char *str) {
189
for (p = str; *p; p++)
190
if ((unsigned char) *p >= 128)
196
char *ascii_filter(const char *str) {
207
for (s = r, d = r; *s; s++)
208
if ((unsigned char) *s < 128)