1 /* dvb_chartbl.c
2  * Routines for handling DVB-SI character tables (as defined in EN 300 468)
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 #include "config.h"
12 
13 #include <glib.h>
14 
15 #include <epan/proto.h>
16 #include <epan/tvbuff.h>
17 #include <epan/value_string.h>
18 
19 #include "dvb_chartbl.h"
20 
21 
22 static const value_string dvb_string_encoding_vals[] = {
23    { DVB_ENCODING_INVALID,  "Incorrect length for encoding" },
24    { DVB_ENCODING_RESERVED, "Reserved for future use" },
25    { DVB_ENCODING_UNKNOWN,  "Unknown/undefined encoding" },
26 
27    { DVB_ENCODING_LATIN,    "Latin (default table)" },
28 
29    { DVB_ENCODING_ISO_8859_1,         "ISO/IEC 8859-1 (West European)" },
30    { DVB_ENCODING_ISO_8859_2,         "ISO/IEC 8859-2 (East European)" },
31    { DVB_ENCODING_ISO_8859_3,         "ISO/IEC 8859-3 (South European)" },
32    { DVB_ENCODING_ISO_8859_4,         "ISO/IEC 8859-4 (North and North-East European)" },
33    { DVB_ENCODING_ISO_8859_5,         "ISO/IEC 8859-5 (Latin/Cyrillic)" },
34    { DVB_ENCODING_ISO_8859_6,         "ISO/IEC 8859-6 (Latin/Arabic)" },
35    { DVB_ENCODING_ISO_8859_7,         "ISO/IEC 8859-7 (Latin/Greek)" },
36    { DVB_ENCODING_ISO_8859_8,         "ISO/IEC 8859-8 (Latin/Hebrew)" },
37    { DVB_ENCODING_ISO_8859_9,         "ISO/IEC 8859-9 (West European & Turkish)" },
38    { DVB_ENCODING_ISO_8859_10,        "ISO/IEC 8859-10 (North European)" },
39    { DVB_ENCODING_ISO_8859_11,        "ISO/IEC 8859-11 (Thai)" },
40    { DVB_ENCODING_ISO_8859_13,        "ISO/IEC 8859-13 (Baltic)" },
41    { DVB_ENCODING_ISO_8859_14,        "ISO/IEC 8859-14 (Celtic)" },
42    { DVB_ENCODING_ISO_8859_15,        "ISO/IEC 8859-15 (West European)" },
43    { DVB_ENCODING_ISO_10646_BMP,      "ISO/IEC 10646 Basic Multilingual Plane" },
44    { DVB_ENCODING_KSX_1001,           "KSX 1001-2004 (Korean character set)" },
45    { DVB_ENCODING_GB_2312,            "GB-2312-1980 (Simplified Chinese)" },
46    { DVB_ENCODING_ISO_10646_BIG5,     "ISO/IEC 10646 BIG5 subset" },
47    { DVB_ENCODING_ISO_10646_UTF8_BMP,
48        "ISO/IEC 10646 Basic Multilingual Plane, UTF-8 encoded" },
49 
50    { 0, NULL }
51 };
52 
53 
54 static dvb_encoding_e
dvb_analyze_string_charset0(guint8 byte0)55 dvb_analyze_string_charset0(guint8 byte0)
56 {
57     switch (byte0) {
58         case 0x01:
59             return DVB_ENCODING_ISO_8859_5;
60         case 0x02:
61             return DVB_ENCODING_ISO_8859_6;
62         case 0x03:
63             return DVB_ENCODING_ISO_8859_7;
64         case 0x04:
65             return DVB_ENCODING_ISO_8859_8;
66         case 0x05:
67             return DVB_ENCODING_ISO_8859_9;
68         case 0x06:
69             return DVB_ENCODING_ISO_8859_10;
70         case 0x07:
71             return DVB_ENCODING_ISO_8859_11;
72         case 0x08:
73             return DVB_ENCODING_RESERVED; /* was reserved for ISO-8859-12 */
74         case 0x09:
75             return DVB_ENCODING_ISO_8859_13;
76         case 0x0A:
77             return DVB_ENCODING_ISO_8859_14;
78         case 0x0B:
79             return DVB_ENCODING_ISO_8859_15;
80         case 0x11:
81             return DVB_ENCODING_ISO_10646_BMP;
82         case 0x12:
83             return DVB_ENCODING_KSX_1001;
84         case 0x13:
85             return DVB_ENCODING_GB_2312;
86         case 0x14:
87             return DVB_ENCODING_ISO_10646_BIG5;
88         case 0x15:
89             return DVB_ENCODING_ISO_10646_UTF8_BMP;
90 
91         default:
92             return DVB_ENCODING_UNKNOWN;
93     }
94 }
95 
96 
97 static dvb_encoding_e
dvb_analyze_string_charset0_10(guint16 byte12)98 dvb_analyze_string_charset0_10(guint16 byte12)
99 {
100     switch (byte12) {
101         case 0x0000:
102              return DVB_ENCODING_RESERVED;
103         case 0x0001:
104          return DVB_ENCODING_ISO_8859_1;
105         case 0x0002:
106          return DVB_ENCODING_ISO_8859_2;
107         case 0x0003:
108          return DVB_ENCODING_ISO_8859_3;
109         case 0x0004:
110          return DVB_ENCODING_ISO_8859_4;
111         case 0x0005:
112          return DVB_ENCODING_ISO_8859_5;
113         case 0x0006:
114          return DVB_ENCODING_ISO_8859_6;
115         case 0x0007:
116          return DVB_ENCODING_ISO_8859_7;
117         case 0x0008:
118          return DVB_ENCODING_ISO_8859_8;
119         case 0x0009:
120          return DVB_ENCODING_ISO_8859_9;
121         case 0x000A:
122          return DVB_ENCODING_ISO_8859_10;
123         case 0x000B:
124          return DVB_ENCODING_ISO_8859_11;
125         case 0x000C:
126          return DVB_ENCODING_RESERVED;
127         case 0x000D:
128          return DVB_ENCODING_ISO_8859_13;
129         case 0x000E:
130          return DVB_ENCODING_ISO_8859_14;
131         case 0x000F:
132          return DVB_ENCODING_ISO_8859_15;
133 
134         default: /* 0x10 XX XX */
135             return DVB_ENCODING_UNKNOWN;
136     }
137 }
138 
139 
140 static dvb_encoding_e
dvb_analyze_string_charset0_1F(guint8 byte1)141 dvb_analyze_string_charset0_1F(guint8 byte1)
142 {
143    /* http://www.dvbservices.com/identifiers/encoding_type_id */
144 
145     switch (byte1) {
146        case 0x00: /* 0x1F 0x00 */
147           return DVB_ENCODING_RESERVED;
148        case 0x01:
149        case 0x02:
150        case 0x03:
151        case 0x04:
152           /* XXX: BBC */
153           return DVB_ENCODING_RESERVED;
154        case 0x05:
155        case 0x06:
156           /* XXX: Malaysian Technical Standards Forum Bhd */
157           return DVB_ENCODING_RESERVED;
158 
159        default: /* 0x1F XX */
160           return DVB_ENCODING_RESERVED;
161     }
162 }
163 
164 
165 guint
dvb_analyze_string_charset(tvbuff_t * tvb,int offset,int length,dvb_encoding_e * encoding)166 dvb_analyze_string_charset(tvbuff_t *tvb, int offset, int length, dvb_encoding_e *encoding)
167 {
168    if (length >= 1) {
169       guint8 byte0 = tvb_get_guint8(tvb, offset + 0);
170 
171       if (byte0 >= 0x20) {
172          /* the first byte is a normal character, not the number of a character table */
173          *encoding = DVB_ENCODING_LATIN;
174          return 0;
175 
176       } else if (byte0 == 0x1F) {
177          if (length >= 2) {
178             *encoding = dvb_analyze_string_charset0_1F(tvb_get_guint8(tvb, offset + 1));
179             return 2;
180          }
181          *encoding = DVB_ENCODING_INVALID;
182          return 1;
183 
184       } else if (byte0 >= 0x16) { /* 16 ... 1E */
185          *encoding = DVB_ENCODING_RESERVED;
186          return 1;
187 
188       } else if (byte0 == 0x10) {
189          if (length >= 3) {
190             *encoding = dvb_analyze_string_charset0_10(tvb_get_ntohs(tvb, offset + 1));
191             return 3;
192          }
193          *encoding = DVB_ENCODING_INVALID;
194          return 1;
195 
196       } else if ((byte0 >= 0x0C && byte0 <= 0x0F)) {
197          *encoding = DVB_ENCODING_RESERVED;
198          return 1;
199       } else {
200          *encoding = dvb_analyze_string_charset0(byte0);
201          return 1;
202       }
203    } else
204       *encoding = DVB_ENCODING_LATIN;
205 
206    return 0;
207 }
208 
209 
210 guint
dvb_enc_to_item_enc(dvb_encoding_e encoding)211 dvb_enc_to_item_enc(dvb_encoding_e encoding)
212 {
213    /* XXX: take ISO control codes into account,
214       e.g. 0x86 - turn emphasis on ; 0x87 - turn emphasis off */
215 
216    switch (encoding) {
217       case DVB_ENCODING_ISO_8859_1:
218          return ENC_ISO_8859_1 | ENC_NA;
219 
220       case DVB_ENCODING_ISO_8859_2:
221          return ENC_ISO_8859_2 | ENC_NA;
222 
223       case DVB_ENCODING_ISO_8859_3:
224          return ENC_ISO_8859_3 | ENC_NA;
225 
226       case DVB_ENCODING_ISO_8859_4:
227          return ENC_ISO_8859_4 | ENC_NA;
228 
229       case DVB_ENCODING_ISO_8859_5:
230          return ENC_ISO_8859_5 | ENC_NA;
231 
232       case DVB_ENCODING_ISO_8859_6:
233          return ENC_ISO_8859_6 | ENC_NA;
234 
235       case DVB_ENCODING_ISO_8859_7:
236          return ENC_ISO_8859_7 | ENC_NA;
237 
238       case DVB_ENCODING_ISO_8859_8:
239          return ENC_ISO_8859_8 | ENC_NA;
240 
241       case DVB_ENCODING_ISO_8859_9:
242          return ENC_ISO_8859_9 | ENC_NA;
243 
244       case DVB_ENCODING_ISO_8859_10:
245          return ENC_ISO_8859_10 | ENC_NA;
246 
247       case DVB_ENCODING_ISO_8859_11:
248          return ENC_ISO_8859_11 | ENC_NA;
249 
250       case DVB_ENCODING_ISO_8859_13:
251          return ENC_ISO_8859_13 | ENC_NA;
252 
253       case DVB_ENCODING_ISO_8859_14:
254          return ENC_ISO_8859_14 | ENC_NA;
255 
256       case DVB_ENCODING_ISO_8859_15:
257          return ENC_ISO_8859_15 | ENC_NA;
258 
259       case DVB_ENCODING_ISO_10646_UTF8_BMP:
260          return ENC_UTF_8 | ENC_NA;
261 
262       default: /* not supported */
263          return ENC_ASCII | ENC_NA;
264    }
265 }
266 
267 
268 void
dvb_add_chartbl(proto_tree * tree,int hf,tvbuff_t * tvb,gint offset,gint length,dvb_encoding_e encoding)269 dvb_add_chartbl(proto_tree *tree, int hf,
270         tvbuff_t *tvb, gint offset, gint length, dvb_encoding_e encoding)
271 {
272     if (tree == NULL)
273         return;
274 
275     if (length==0) {
276         proto_item *pi;
277 
278         pi = proto_tree_add_bytes_format(tree, hf, tvb, 0, 0, NULL,
279                 "Default character table (Latin)");
280         proto_item_set_generated(pi);
281     }
282     else {
283         proto_tree_add_bytes_format_value(tree, hf,
284             tvb, offset, length, NULL, "%s (%s)",
285             val_to_str_const(encoding, dvb_string_encoding_vals, "Unknown"),
286             tvb_bytes_to_str_punct(PNODE_POOL(tree), tvb, offset, length, ' '));
287     }
288 }
289 
290 /*
291  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
292  *
293  * Local variables:
294  * c-basic-offset: 4
295  * tab-width: 8
296  * indent-tabs-mode: nil
297  * End:
298  *
299  * vi: set shiftwidth=4 tabstop=8 expandtab:
300  * :indentSize=4:tabSize=8:noTabs=true:
301  */
302