vdr  2.4.7
si.c
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (c) 2003 by Marcel Wiesweg *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation; either version 2 of the License, or *
7  * (at your option) any later version. *
8  * *
9  * $Id: si.c 4.3 2020/12/19 14:41:41 kls Exp $
10  * *
11  ***************************************************************************/
12 
13 #include "si.h"
14 #include <errno.h>
15 #include <iconv.h>
16 #include <malloc.h>
17 #include <stdlib.h> // for broadcaster stupidity workaround
18 #include <string.h>
19 #include "descriptor.h"
20 
21 namespace SI {
22 
24 }
25 
26 Object::Object(CharArray &d) : data(d) {
27 }
28 
29 void Object::setData(const unsigned char*d, int size, bool doCopy) {
30  data.assign(d, size, doCopy);
31 }
32 
34  data=d;
35 }
36 
37 bool Object::checkSize(int offset) {
38  return data.checkSize(offset);
39 }
40 
41 Section::Section(const unsigned char *data, bool doCopy) {
42  setData(data, getLength(data), doCopy);
43 }
44 
46  return getTableId(data.getData());
47 }
48 
50  return getLength(data.getData());
51 }
52 
53 TableId Section::getTableId(const unsigned char *d) {
54  return (TableId)((const SectionHeader *)d)->table_id;
55 }
56 
57 int Section::getLength(const unsigned char *d) {
58  return HILO(((const SectionHeader *)d)->section_length)+sizeof(SectionHeader);
59 }
60 
62  return CRC32::isValid((const char *)data.getData(), getLength()/*, data.FourBytes(getLength()-4)*/);
63 }
64 
66  if (!isCRCValid())
67  return false;
68  CheckParse();
69  return isValid();
70 }
71 
74 }
75 
76 int NumberedSection::getTableIdExtension(const unsigned char *d) {
77  return HILO(((const ExtendedSectionHeader *)d)->table_id_extension);
78 }
79 
81  return data.getData<ExtendedSectionHeader>()->current_next_indicator;
82 }
83 
85  return data.getData<ExtendedSectionHeader>()->version_number;
86 }
87 
89  return data.getData<ExtendedSectionHeader>()->section_number;
90 }
91 
93  return data.getData<ExtendedSectionHeader>()->last_section_number;
94 }
95 
97  return getLength(data.getData());
98 }
99 
101  return getDescriptorTag(data.getData());
102 }
103 
104 int Descriptor::getLength(const unsigned char *d) {
105  return ((const DescriptorHeader*)d)->descriptor_length+sizeof(DescriptorHeader);
106 }
107 
109  return (DescriptorTag)((const DescriptorHeader*)d)->descriptor_tag;
110 }
111 
113  if (isValid() && it.i<getLength()) {
114  return createDescriptor(it.i, true);
115  }
116  return 0;
117 }
118 
119 Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor) {
120  Descriptor *d=0;
121  int len;
122  if (isValid() && it.i<(len=getLength())) {
123  const unsigned char *p=data.getData(it.i);
124  const unsigned char *end=p+len-it.i;
125  while (p < end) {
126  if (Descriptor::getDescriptorTag(p) == tag) {
127  d=createDescriptor(it.i, returnUnimplemetedDescriptor);
128  if (d)
129  break;
130  }
131  it.i+=Descriptor::getLength(p);
132  p+=Descriptor::getLength(p);
133  }
134  }
135  return d;
136 }
137 
138 Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplementedDescriptor) {
139  Descriptor *d=0;
140  int len;
141  if (isValid() && it.i<(len=getLength())) {
142  const unsigned char *p=data.getData(it.i);
143  const unsigned char *end=p+len-it.i;
144  while (p < end) {
145  for (int u=0; u<arrayLength;u++)
146  if (Descriptor::getDescriptorTag(p) == tags[u]) {
147  d=createDescriptor(it.i, returnUnimplementedDescriptor);
148  break;
149  }
150  if (d)
151  break; //length is added to it.i by createDescriptor, break here
152  it.i+=Descriptor::getLength(p);
153  p+=Descriptor::getLength(p);
154  }
155  }
156  return d;
157 }
158 
159 Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) {
161  return 0;
162  Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor);
163  if (!d)
164  return 0;
165  i+=d->getLength();
166  d->CheckParse();
167  return d;
168 }
169 
171  const unsigned char *p=data.getData();
172  const unsigned char *end=p+getLength();
173  int count=0;
174  while (p < end) {
175  count++;
176  p+=Descriptor::getLength(p);
177  }
178  return count;
179 }
180 
182  array=0;
183  length=0;
185 }
186 
189  Delete();
190  delete[] array;
191 }
192 
194  for (int i=0;i<length;i++)
195  if (array[i]!=0) {
196  delete array[i];
197  array[i]=0;
198  }
199 }
200 
202  if (!array) {
204  array=new GroupDescriptor*[length]; //numbering is zero-based
205  for (int i=0;i<length;i++)
206  array[i]=0;
207  } else if (length != d->getLastDescriptorNumber()+1)
208  return false; //avoid crash in case of misuse
209  if (length <= d->getDescriptorNumber())
210  return false; // see http://www.vdr-portal.de/board60-linux/board14-betriebssystem/board69-c-t-vdr/p1025777-segfault-mit-vdr-1-7-21/#post1025777
211  array[d->getDescriptorNumber()]=d;
212  return true;
213 }
214 
216  for (int i=0;i<length;i++)
217  if (array[i]==0)
218  return false;
219  return true;
220 }
221 
223  int len=getLength();
224  if (len < 0 || len > 4095)
225  return strdup("text error"); // caller will delete it!
226  char *data=new char(len+1); // FIXME If this function is ever actually used, this buffer might
227  // need to be bigger in order to hold the string as UTF-8.
228  // Maybe decodeText should dynamically handle this? kls 2007-06-10
229  decodeText(data, len+1);
230  return data;
231 }
232 
233 char *String::getText(char *buffer, int size, const char **fromCode) {
234  int len=getLength();
235  if (len < 0 || len >= size) {
236  strncpy(buffer, "text error", size);
237  buffer[size-1] = 0;
238  return buffer;
239  }
240  decodeText(buffer, size, fromCode);
241  return buffer;
242 }
243 
244 char *String::getText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion) {
245  int len=getLength();
246  if (len < 0 || len >= sizeBuffer) {
247  strncpy(buffer, "text error", sizeBuffer);
248  buffer[sizeBuffer-1] = 0;
249  *shortVersion = 0;
250  return buffer;
251  }
252  decodeText(buffer, shortVersion, sizeBuffer, sizeShortVersion);
253  return buffer;
254 }
255 
256 static const char *CharacterTables1[] = {
257  NULL, // 0x00
258  "ISO-8859-5", // 0x01
259  "ISO-8859-6", // 0x02
260  "ISO-8859-7", // 0x03
261  "ISO-8859-8", // 0x04
262  "ISO-8859-9", // 0x05
263  "ISO-8859-10", // 0x06
264  "ISO-8859-11", // 0x07
265  "ISO-8859-12", // 0x08
266  "ISO-8859-13", // 0x09
267  "ISO-8859-14", // 0x0A
268  "ISO-8859-15", // 0x0B
269  NULL, // 0x0C
270  NULL, // 0x0D
271  NULL, // 0x0E
272  NULL, // 0x0F
273  NULL, // 0x10
274  "UTF-16", // 0x11
275  "EUC-KR", // 0x12
276  "GB2312", // 0x13
277  "GBK", // 0x14
278  "UTF-8", // 0x15
279  NULL, // 0x16
280  NULL, // 0x17
281  NULL, // 0x18
282  NULL, // 0x19
283  NULL, // 0x1A
284  NULL, // 0x1B
285  NULL, // 0x1C
286  NULL, // 0x1D
287  NULL, // 0x1E
288  NULL, // 0x1F
289 };
290 
291 #define SingleByteLimit 0x0B
292 
293 static const char *CharacterTables2[] = {
294  NULL, // 0x00
295  "ISO-8859-1", // 0x01
296  "ISO-8859-2", // 0x02
297  "ISO-8859-3", // 0x03
298  "ISO-8859-4", // 0x04
299  "ISO-8859-5", // 0x05
300  "ISO-8859-6", // 0x06
301  "ISO-8859-7", // 0x07
302  "ISO-8859-8", // 0x08
303  "ISO-8859-9", // 0x09
304  "ISO-8859-10", // 0x0A
305  "ISO-8859-11", // 0x0B
306  NULL, // 0x0C
307  "ISO-8859-13", // 0x0D
308  "ISO-8859-14", // 0x0E
309  "ISO-8859-15", // 0x0F
310 };
311 
312 #define NumEntries(Table) (sizeof(Table) / sizeof(char *))
313 
314 static char *SystemCharacterTable = NULL;
316 
318 {
320 }
321 
322 static char *OverrideCharacterTable = NULL;
323 
324 bool SetOverrideCharacterTable(const char *CharacterTable)
325 {
327  OverrideCharacterTable = CharacterTable ? strdup(CharacterTable) : NULL;
329  // Check whether the character table is known:
330  iconv_t cd = iconv_open(SystemCharacterTable, OverrideCharacterTable);
331  if (cd != (iconv_t)-1) {
332  iconv_close(cd);
333  return true;
334  }
335  }
336  return false;
337 }
338 
339 bool SetSystemCharacterTable(const char *CharacterTable) {
340  free(SystemCharacterTable);
341  SystemCharacterTable = CharacterTable ? strdup(CharacterTable) : NULL;
343  if (SystemCharacterTable) {
344  // Check whether the character table is known and "single byte":
345  char a[] = "ä; char *pa = a; char b[10]; char *pb = b; size_t la = strlen(a); size_t lb = sizeof(b); iconv_t cd = iconv_open(SystemCharacterTable, "ISO-8859-1"); if (cd != (iconv_t)-1) { if (iconv(cd, &pa, &la, &pb, &lb) != size_t(-1)) { *pb = 0; SystemCharacterTableIsSingleByte = strlen(b) == 1; } iconv_close(cd); return true; } } return false; } const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte) { const char *cs = "ISO6937"; // Workaround for broadcaster stupidity: according to // "ETSI EN 300 468" the default character set is ISO6937. But unfortunately some // broadcasters actually use ISO-8859-9, but fail to correctly announce that. if (OverrideCharacterTable) cs = OverrideCharacterTable; if (isSingleByte) *isSingleByte = false; if (length <= 0) return cs; unsigned int tag = buffer[0]; if (tag >= 0x20) return cs; if (tag == 0x10) { if (length >= 3) { tag = (buffer[1] << 8) | buffer[2]; if (tag < NumEntries(CharacterTables2) && CharacterTables2[tag]) { buffer += 3; length -= 3; if (isSingleByte) *isSingleByte = true; return CharacterTables2[tag]; } } } else if (tag < NumEntries(CharacterTables1) && CharacterTables1[tag]) { buffer += 1; length -= 1; if (isSingleByte) *isSingleByte = tag <= SingleByteLimit; return CharacterTables1[tag]; } return cs; } // A similar version is used in VDR/tools.c: static int Utf8CharLen(const char *s) { if (SystemCharacterTableIsSingleByte) return 1; #define MT(s, m, v) ((*(s) & (m)) == (v)) // Mask Test if (MT(s, 0xE0, 0xC0) && MT(s + 1, 0xC0, 0x80)) return 2; if (MT(s, 0xF0, 0xE0) && MT(s + 1, 0xC0, 0x80) && MT(s + 2, 0xC0, 0x80)) return 3; if (MT(s, 0xF8, 0xF0) && MT(s + 1, 0xC0, 0x80) && MT(s + 2, 0xC0, 0x80) && MT(s + 3, 0xC0, 0x80)) return 4; return 1; } size_t convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode) { bool converted = false; char *result = to; if (SystemCharacterTable && fromCode) { iconv_t cd = iconv_open(SystemCharacterTable, fromCode); if (cd != (iconv_t)-1) { char *fromPtr = (char *)from; while (fromLength > 0 && toLength > 1) { if (iconv(cd, &fromPtr, &fromLength, &to, &toLength) == size_t(-1)) { if (errno == EILSEQ) { // A character can't be converted, so mark it with '?' and proceed: fromPtr++; fromLength--; *to++ = '?'; toLength--; } else break; } } *to = 0; iconv_close(cd); converted = true; } } if (!converted) { size_t len = fromLength; if (len >= toLength) len = toLength - 1; strncpy(to, from, len); to[len] = 0; } // Handle control codes: to = result; size_t len = strlen(to); while (len > 0) { int l = Utf8CharLen(to); if (l <= 2) { unsigned char *p = (unsigned char *)to; if (l == 2 && *p == 0xC2) // UTF-8 sequence p++; bool Move = true; switch (*p) { case 0x8A: *to = '\n'; break; case 0xA0: *to = ' '; break; default: Move = false; } if (l == 2 && Move) { memmove(p, p + 1, len - 1); // we also copy the terminating 0! len -= 1; l = 1; } } to += l; len -= l; } return strlen(result); } // originally from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de> void String::decodeText(char *buffer, int size, const char **fromCode) { const unsigned char *from=data.getData(0); char *to=buffer; int len=getLength(); if (len <= 0) { *to = '\0'; return; } const char *cs = getCharacterTable(from, len); if (fromCode) { if (len >= size) len = size - 1; strncpy(buffer, (const char *)from, len); buffer[len] = 0; if (!*fromCode) *fromCode = cs; } else convertCharacterTable((const char *)from, len, to, size, cs); } void String::decodeText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion) { decodeText(buffer, sizeBuffer); if (!*buffer) { *shortVersion = '\0'; return; } // Handle control codes: char *to=buffer; int len=strlen(to); int IsShortName=0; while (len > 0) { int l = Utf8CharLen(to); unsigned char *p = (unsigned char *)to; if (l == 2 && *p == 0xC2) // UTF-8 sequence p++; if (*p == 0x86 || *p == 0x87) { IsShortName += (*p == 0x86) ? 1 : -1; memmove(to, to + l, len - l + 1); // we also copy the terminating 0! len -= l; l = 0; } if (l && IsShortName) { if (l < sizeShortVersion) { for (int i = 0; i < l; i++) *shortVersion++ = to[i]; sizeShortVersion -= l; } } to += l; len -= l; } *shortVersion = '\0'; } Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor) { Descriptor *d=0; switch (domain) { case SI: switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) { case CaDescriptorTag: d=new CaDescriptor(); break; case CarouselIdentifierDescriptorTag: d=new CarouselIdentifierDescriptor(); break; case AVCDescriptorTag: d=new AVCDescriptor(); break; case NetworkNameDescriptorTag: d=new NetworkNameDescriptor(); break; case ServiceListDescriptorTag: d=new ServiceListDescriptor(); break; case SatelliteDeliverySystemDescriptorTag: d=new SatelliteDeliverySystemDescriptor(); break; case CableDeliverySystemDescriptorTag: d=new CableDeliverySystemDescriptor(); break; case TerrestrialDeliverySystemDescriptorTag: d=new TerrestrialDeliverySystemDescriptor(); break; case BouquetNameDescriptorTag: d=new BouquetNameDescriptor(); break; case ServiceDescriptorTag: d=new ServiceDescriptor(); break; case NVODReferenceDescriptorTag: d=new NVODReferenceDescriptor(); break; case TimeShiftedServiceDescriptorTag: d=new TimeShiftedServiceDescriptor(); break; case ComponentDescriptorTag: d=new ComponentDescriptor(); break; case StreamIdentifierDescriptorTag: d=new StreamIdentifierDescriptor(); break; case SubtitlingDescriptorTag: d=new SubtitlingDescriptor(); break; case MultilingualNetworkNameDescriptorTag: d=new MultilingualNetworkNameDescriptor(); break; case MultilingualBouquetNameDescriptorTag: d=new MultilingualBouquetNameDescriptor(); break; case MultilingualServiceNameDescriptorTag: d=new MultilingualServiceNameDescriptor(); break; case MultilingualComponentDescriptorTag: d=new MultilingualComponentDescriptor(); break; case PrivateDataSpecifierDescriptorTag: d=new PrivateDataSpecifierDescriptor(); break; case ServiceMoveDescriptorTag: d=new ServiceMoveDescriptor(); break; case FrequencyListDescriptorTag: d=new FrequencyListDescriptor(); break; case ServiceIdentifierDescriptorTag: d=new ServiceIdentifierDescriptor(); break; case CaIdentifierDescriptorTag: d=new CaIdentifierDescriptor(); break; case ShortEventDescriptorTag: d=new ShortEventDescriptor(); break; case ExtendedEventDescriptorTag: d=new ExtendedEventDescriptor(); break; case TimeShiftedEventDescriptorTag: d=new TimeShiftedEventDescriptor(); break; case ContentDescriptorTag: d=new ContentDescriptor(); break; case ParentalRatingDescriptorTag: d=new ParentalRatingDescriptor(); break; case TeletextDescriptorTag: case VBITeletextDescriptorTag: d=new TeletextDescriptor(); break; case ApplicationSignallingDescriptorTag: d=new ApplicationSignallingDescriptor(); break; case LocalTimeOffsetDescriptorTag: d=new LocalTimeOffsetDescriptor(); break; case LinkageDescriptorTag: d=new LinkageDescriptor(); break; case ISO639LanguageDescriptorTag: d=new ISO639LanguageDescriptor(); break; case PDCDescriptorTag: d=new PDCDescriptor(); break; case AncillaryDataDescriptorTag: d=new AncillaryDataDescriptor(); break; case S2SatelliteDeliverySystemDescriptorTag: d=new S2SatelliteDeliverySystemDescriptor(); break; case ExtensionDescriptorTag: d=new ExtensionDescriptor(); break; case LogicalChannelDescriptorTag: d=new LogicalChannelDescriptor(); break; case HdSimulcastLogicalChannelDescriptorTag: d=new HdSimulcastLogicalChannelDescriptor(); break; case RegistrationDescriptorTag: d=new RegistrationDescriptor(); break; case ContentIdentifierDescriptorTag: d=new ContentIdentifierDescriptor(); break; case DefaultAuthorityDescriptorTag: d=new DefaultAuthorityDescriptor(); break; //note that it is no problem to implement one //of the unimplemented descriptors. //defined in ISO-13818-1 case VideoStreamDescriptorTag: case AudioStreamDescriptorTag: case HierarchyDescriptorTag: case DataStreamAlignmentDescriptorTag: case TargetBackgroundGridDescriptorTag: case VideoWindowDescriptorTag: case SystemClockDescriptorTag: case MultiplexBufferUtilizationDescriptorTag: case CopyrightDescriptorTag: case MaximumBitrateDescriptorTag: case PrivateDataIndicatorDescriptorTag: case SmoothingBufferDescriptorTag: case STDDescriptorTag: case IBPDescriptorTag: //defined in ETSI EN 300 468 case StuffingDescriptorTag: case VBIDataDescriptorTag: case CountryAvailabilityDescriptorTag: case MocaicDescriptorTag: case TelephoneDescriptorTag: case CellListDescriptorTag: case CellFrequencyLinkDescriptorTag: case ServiceAvailabilityDescriptorTag: case ShortSmoothingBufferDescriptorTag: case PartialTransportStreamDescriptorTag: case DataBroadcastDescriptorTag: case DataBroadcastIdDescriptorTag: case ScramblingDescriptorTag: case AC3DescriptorTag: case DSNGDescriptorTag: case AnnouncementSupportDescriptorTag: case AdaptationFieldDataDescriptorTag: case TransportStreamDescriptorTag: //defined in ETSI EN 300 468 v 1.7.1 case RelatedContentDescriptorTag: case TVAIdDescriptorTag: case TimeSliceFecIdentifierDescriptorTag: case ECMRepetitionRateDescriptorTag: case EnhancedAC3DescriptorTag: case DTSDescriptorTag: case AACDescriptorTag: default: if (!returnUnimplemetedDescriptor) return 0; d=new UnimplementedDescriptor(); break; } break; case MHP: switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) { // They once again start with 0x00 (see page 234, MHP specification) case MHP_ApplicationDescriptorTag: d=new MHP_ApplicationDescriptor(); break; case MHP_ApplicationNameDescriptorTag: d=new MHP_ApplicationNameDescriptor(); break; case MHP_TransportProtocolDescriptorTag: d=new MHP_TransportProtocolDescriptor(); break; case MHP_DVBJApplicationDescriptorTag: d=new MHP_DVBJApplicationDescriptor(); break; case MHP_DVBJApplicationLocationDescriptorTag: d=new MHP_DVBJApplicationLocationDescriptor(); break; case MHP_SimpleApplicationLocationDescriptorTag: d=new MHP_SimpleApplicationLocationDescriptor(); break; // 0x05 - 0x0A is unimplemented this library case MHP_ExternalApplicationAuthorisationDescriptorTag: case MHP_IPv4RoutingDescriptorTag: case MHP_IPv6RoutingDescriptorTag: case MHP_DVBHTMLApplicationDescriptorTag: case MHP_DVBHTMLApplicationLocationDescriptorTag: case MHP_DVBHTMLApplicationBoundaryDescriptorTag: case MHP_ApplicationIconsDescriptorTag: case MHP_PrefetchDescriptorTag: case MHP_DelegatedApplicationDescriptorTag: case MHP_ApplicationStorageDescriptorTag: default: if (!returnUnimplemetedDescriptor) return 0; d=new UnimplementedDescriptor(); break; } break; case PCIT: switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) { case ContentDescriptorTag: d=new ContentDescriptor(); break; case ShortEventDescriptorTag: d=new ShortEventDescriptor(); break; case ExtendedEventDescriptorTag: d=new ExtendedEventDescriptor(); break; case PremiereContentTransmissionDescriptorTag: d=new PremiereContentTransmissionDescriptor(); break; default: if (!returnUnimplemetedDescriptor) return 0; d=new UnimplementedDescriptor(); break; } break; default: ; // unknown domain, nothing to do } d->setData(da); return d; } } //end of namespace ";
346  char *pa = a;
347  char b[10];
348  char *pb = b;
349  size_t la = strlen(a);
350  size_t lb = sizeof(b);
351  iconv_t cd = iconv_open(SystemCharacterTable, "ISO-8859-1");
352  if (cd != (iconv_t)-1) {
353  if (iconv(cd, &pa, &la, &pb, &lb) != size_t(-1)) {
354  *pb = 0;
355  SystemCharacterTableIsSingleByte = strlen(b) == 1;
356  }
357  iconv_close(cd);
358  return true;
359  }
360  }
361  return false;
362 }
363 
364 const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte) {
365  const char *cs = "ISO6937";
366  // Workaround for broadcaster stupidity: according to
367  // "ETSI EN 300 468" the default character set is ISO6937. But unfortunately some
368  // broadcasters actually use ISO-8859-9, but fail to correctly announce that.
371  if (isSingleByte)
372  *isSingleByte = false;
373  if (length <= 0)
374  return cs;
375  unsigned int tag = buffer[0];
376  if (tag >= 0x20)
377  return cs;
378  if (tag == 0x10) {
379  if (length >= 3) {
380  tag = (buffer[1] << 8) | buffer[2];
381  if (tag < NumEntries(CharacterTables2) && CharacterTables2[tag]) {
382  buffer += 3;
383  length -= 3;
384  if (isSingleByte)
385  *isSingleByte = true;
386  return CharacterTables2[tag];
387  }
388  }
389  } else if (tag < NumEntries(CharacterTables1) && CharacterTables1[tag]) {
390  buffer += 1;
391  length -= 1;
392  if (isSingleByte)
393  *isSingleByte = tag <= SingleByteLimit;
394  return CharacterTables1[tag];
395  }
396  return cs;
397 }
398 
399 // A similar version is used in VDR/tools.c:
400 static int Utf8CharLen(const char *s)
401 {
403  return 1;
404 #define MT(s, m, v) ((*(s) & (m)) == (v)) // Mask Test
405  if (MT(s, 0xE0, 0xC0) && MT(s + 1, 0xC0, 0x80))
406  return 2;
407  if (MT(s, 0xF0, 0xE0) && MT(s + 1, 0xC0, 0x80) && MT(s + 2, 0xC0, 0x80))
408  return 3;
409  if (MT(s, 0xF8, 0xF0) && MT(s + 1, 0xC0, 0x80) && MT(s + 2, 0xC0, 0x80) && MT(s + 3, 0xC0, 0x80))
410  return 4;
411  return 1;
412 }
413 
414 size_t convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode)
415 {
416  bool converted = false;
417  char *result = to;
418  if (SystemCharacterTable && fromCode) {
419  iconv_t cd = iconv_open(SystemCharacterTable, fromCode);
420  if (cd != (iconv_t)-1) {
421  char *fromPtr = (char *)from;
422  while (fromLength > 0 && toLength > 1) {
423  if (iconv(cd, &fromPtr, &fromLength, &to, &toLength) == size_t(-1)) {
424  if (errno == EILSEQ) {
425  // A character can't be converted, so mark it with '?' and proceed:
426  fromPtr++;
427  fromLength--;
428  *to++ = '?';
429  toLength--;
430  }
431  else
432  break;
433  }
434  }
435  *to = 0;
436  iconv_close(cd);
437  converted = true;
438  }
439  }
440  if (!converted) {
441  size_t len = fromLength;
442  if (len >= toLength)
443  len = toLength - 1;
444  strncpy(to, from, len);
445  to[len] = 0;
446  }
447  // Handle control codes:
448  to = result;
449  size_t len = strlen(to);
450  while (len > 0) {
451  int l = Utf8CharLen(to);
452  if (l <= 2) {
453  unsigned char *p = (unsigned char *)to;
454  if (l == 2 && *p == 0xC2) // UTF-8 sequence
455  p++;
456  bool Move = true;
457  switch (*p) {
458  case 0x8A: *to = '\n'; break;
459  case 0xA0: *to = ' '; break;
460  default: Move = false;
461  }
462  if (l == 2 && Move) {
463  memmove(p, p + 1, len - 1); // we also copy the terminating 0!
464  len -= 1;
465  l = 1;
466  }
467  }
468  to += l;
469  len -= l;
470  }
471  return strlen(result);
472 }
473 
474 // originally from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de>
475 void String::decodeText(char *buffer, int size, const char **fromCode) {
476  const unsigned char *from=data.getData(0);
477  char *to=buffer;
478  int len=getLength();
479  if (len <= 0) {
480  *to = '\0';
481  return;
482  }
483  const char *cs = getCharacterTable(from, len);
484  if (fromCode) {
485  if (len >= size)
486  len = size - 1;
487  strncpy(buffer, (const char *)from, len);
488  buffer[len] = 0;
489  if (!*fromCode)
490  *fromCode = cs;
491  }
492  else
493  convertCharacterTable((const char *)from, len, to, size, cs);
494 }
495 
496 void String::decodeText(char *buffer, char *shortVersion, int sizeBuffer, int sizeShortVersion) {
497  decodeText(buffer, sizeBuffer);
498  if (!*buffer) {
499  *shortVersion = '\0';
500  return;
501  }
502  // Handle control codes:
503  char *to=buffer;
504  int len=strlen(to);
505  int IsShortName=0;
506  while (len > 0) {
507  int l = Utf8CharLen(to);
508  unsigned char *p = (unsigned char *)to;
509  if (l == 2 && *p == 0xC2) // UTF-8 sequence
510  p++;
511  if (*p == 0x86 || *p == 0x87) {
512  IsShortName += (*p == 0x86) ? 1 : -1;
513  memmove(to, to + l, len - l + 1); // we also copy the terminating 0!
514  len -= l;
515  l = 0;
516  }
517  if (l && IsShortName) {
518  if (l < sizeShortVersion) {
519  for (int i = 0; i < l; i++)
520  *shortVersion++ = to[i];
521  sizeShortVersion -= l;
522  }
523  }
524  to += l;
525  len -= l;
526  }
527  *shortVersion = '\0';
528 }
529 
530 Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor) {
531  Descriptor *d=0;
532  switch (domain) {
533  case SI:
535  case CaDescriptorTag:
536  d=new CaDescriptor();
537  break;
540  break;
541  case AVCDescriptorTag:
542  d=new AVCDescriptor();
543  break;
545  d=new NetworkNameDescriptor();
546  break;
548  d=new ServiceListDescriptor();
549  break;
552  break;
555  break;
558  break;
560  d=new BouquetNameDescriptor();
561  break;
563  d=new ServiceDescriptor();
564  break;
566  d=new NVODReferenceDescriptor();
567  break;
570  break;
572  d=new ComponentDescriptor();
573  break;
576  break;
578  d=new SubtitlingDescriptor();
579  break;
582  break;
585  break;
588  break;
591  break;
594  break;
596  d=new ServiceMoveDescriptor();
597  break;
599  d=new FrequencyListDescriptor();
600  break;
603  break;
605  d=new CaIdentifierDescriptor();
606  break;
608  d=new ShortEventDescriptor();
609  break;
611  d=new ExtendedEventDescriptor();
612  break;
615  break;
617  d=new ContentDescriptor();
618  break;
620  d=new ParentalRatingDescriptor();
621  break;
624  d=new TeletextDescriptor();
625  break;
628  break;
631  break;
633  d=new LinkageDescriptor();
634  break;
636  d=new ISO639LanguageDescriptor();
637  break;
638  case PDCDescriptorTag:
639  d=new PDCDescriptor();
640  break;
642  d=new AncillaryDataDescriptor();
643  break;
646  break;
648  d=new ExtensionDescriptor();
649  break;
651  d=new LogicalChannelDescriptor();
652  break;
655  break;
657  d=new RegistrationDescriptor();
658  break;
661  break;
664  break;
665 
666  //note that it is no problem to implement one
667  //of the unimplemented descriptors.
668 
669  //defined in ISO-13818-1
682  case STDDescriptorTag:
683  case IBPDescriptorTag:
684 
685  //defined in ETSI EN 300 468
689  case MocaicDescriptorTag:
699  case AC3DescriptorTag:
700  case DSNGDescriptorTag:
704 
705  //defined in ETSI EN 300 468 v 1.7.1
707  case TVAIdDescriptorTag:
711  case DTSDescriptorTag:
712  case AACDescriptorTag:
713  default:
714  if (!returnUnimplemetedDescriptor)
715  return 0;
716  d=new UnimplementedDescriptor();
717  break;
718  }
719  break;
720  case MHP:
722  // They once again start with 0x00 (see page 234, MHP specification)
725  break;
728  break;
731  break;
734  break;
737  break;
740  break;
741  // 0x05 - 0x0A is unimplemented this library
752  default:
753  if (!returnUnimplemetedDescriptor)
754  return 0;
755  d=new UnimplementedDescriptor();
756  break;
757  }
758  break;
759  case PCIT:
762  d=new ContentDescriptor();
763  break;
765  d=new ShortEventDescriptor();
766  break;
768  d=new ExtendedEventDescriptor();
769  break;
772  break;
773  default:
774  if (!returnUnimplemetedDescriptor)
775  return 0;
776  d=new UnimplementedDescriptor();
777  break;
778  }
779  break;
780  default: ; // unknown domain, nothing to do
781  }
782  d->setData(da);
783  return d;
784 }
785 
786 } //end of namespace
bool isValid()
Definition: util.h:150
bool CheckCRCAndParse()
Definition: si.c:65
bool isCRCValid()
Definition: si.c:61
void assign(const unsigned char *data, int size, bool doCopy=true)
Definition: util.c:50
const unsigned char * getData() const
Definition: util.h:51
bool checkSize(int offset)
Definition: util.h:63
void Delete()
Definition: si.c:193
GroupDescriptor ** array
Definition: si.h:493
bool isComplete()
Definition: si.c:215
bool Add(GroupDescriptor *d)
Definition: si.c:201
bool deleteOnDesctruction
Definition: si.h:494
DescriptorGroup(bool deleteOnDesctruction=true)
Definition: si.c:181
~DescriptorGroup()
Definition: si.c:187
int getNumberOfDescriptors()
Definition: si.c:170
DescriptorTagDomain domain
Definition: si.h:426
Descriptor * getNext(Iterator &it)
Definition: si.c:112
Descriptor * createDescriptor(int &i, bool returnUnimplemetedDescriptor)
Definition: si.c:159
DescriptorTag getDescriptorTag() const
Definition: si.c:100
virtual int getLength()
Definition: si.c:96
static Descriptor * getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor)
Definition: si.c:530
virtual int getLastDescriptorNumber()=0
virtual int getDescriptorNumber()=0
int getTableIdExtension() const
Definition: si.c:72
bool getCurrentNextIndicator() const
Definition: si.c:80
int getSectionNumber() const
Definition: si.c:88
int getLastSectionNumber() const
Definition: si.c:92
int getVersionNumber() const
Definition: si.c:84
void setData(const unsigned char *data, int size, bool doCopy=true)
Definition: si.c:29
bool isValid()
Definition: si.h:238
Object()
Definition: si.c:23
bool checkSize(int offset)
Definition: si.c:37
CharArray data
Definition: si.h:241
void CheckParse()
Definition: util.c:182
virtual int getLength()
Definition: si.c:49
TableId getTableId() const
Definition: si.c:45
Section()
Definition: si.h:254
void decodeText(char *buffer, int size, const char **fromCode=NULL)
Definition: si.c:475
char * getText()
Definition: si.c:222
virtual int getLength()
Definition: si.h:294
Definition: descriptor.c:16
static const char * CharacterTables2[]
Definition: si.c:293
static int Utf8CharLen(const char *s)
Definition: si.c:400
const char * getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte)
Definition: si.c:364
bool SetSystemCharacterTable(const char *CharacterTable)
Definition: si.c:339
size_t convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode)
Definition: si.c:414
TableId
Definition: si.h:23
DescriptorTagDomain
Definition: si.h:195
@ PCIT
Definition: si.h:195
@ SI
Definition: si.h:195
@ MHP
Definition: si.h:195
bool SystemCharacterTableIsSingleByte
Definition: si.c:315
bool systemCharacterTableIsSingleByte(void)
Definition: si.c:317
DescriptorTag
Definition: si.h:51
@ AudioStreamDescriptorTag
Definition: si.h:54
@ ECMRepetitionRateDescriptorTag
Definition: si.h:135
@ TVAIdDescriptorTag
Definition: si.h:132
@ MHP_PrefetchDescriptorTag
Definition: si.h:182
@ MocaicDescriptorTag
Definition: si.h:95
@ DTSDescriptorTag
Definition: si.h:138
@ CopyrightDescriptorTag
Definition: si.h:64
@ MHP_SimpleApplicationLocationDescriptorTag
Definition: si.h:185
@ StreamIdentifierDescriptorTag
Definition: si.h:96
@ VideoWindowDescriptorTag
Definition: si.h:59
@ MultiplexBufferUtilizationDescriptorTag
Definition: si.h:63
@ RelatedContentDescriptorTag
Definition: si.h:131
@ MultilingualComponentDescriptorTag
Definition: si.h:108
@ NVODReferenceDescriptorTag
Definition: si.h:89
@ EnhancedAC3DescriptorTag
Definition: si.h:137
@ TeletextDescriptorTag
Definition: si.h:100
@ ServiceMoveDescriptorTag
Definition: si.h:110
@ ServiceDescriptorTag
Definition: si.h:86
@ PrivateDataSpecifierDescriptorTag
Definition: si.h:109
@ ScramblingDescriptorTag
Definition: si.h:115
@ PartialTransportStreamDescriptorTag
Definition: si.h:113
@ CountryAvailabilityDescriptorTag
Definition: si.h:87
@ CaDescriptorTag
Definition: si.h:60
@ CarouselIdentifierDescriptorTag
Definition: si.h:71
@ DataBroadcastDescriptorTag
Definition: si.h:114
@ ExtendedEventDescriptorTag
Definition: si.h:92
@ VBITeletextDescriptorTag
Definition: si.h:84
@ S2SatelliteDeliverySystemDescriptorTag
Definition: si.h:136
@ MHP_DVBHTMLApplicationDescriptorTag
Definition: si.h:178
@ CableDeliverySystemDescriptorTag
Definition: si.h:82
@ ShortEventDescriptorTag
Definition: si.h:91
@ PrivateDataIndicatorDescriptorTag
Definition: si.h:66
@ ServiceAvailabilityDescriptorTag
Definition: si.h:128
@ MaximumBitrateDescriptorTag
Definition: si.h:65
@ CaIdentifierDescriptorTag
Definition: si.h:97
@ ComponentDescriptorTag
Definition: si.h:94
@ AVCDescriptorTag
Definition: si.h:74
@ ExtensionDescriptorTag
Definition: si.h:140
@ TransportStreamDescriptorTag
Definition: si.h:117
@ HdSimulcastLogicalChannelDescriptorTag
Definition: si.h:146
@ MHP_DelegatedApplicationDescriptorTag
Definition: si.h:183
@ TimeShiftedServiceDescriptorTag
Definition: si.h:90
@ ServiceIdentifierDescriptorTag
Definition: si.h:127
@ MultilingualNetworkNameDescriptorTag
Definition: si.h:105
@ MHP_ApplicationIconsDescriptorTag
Definition: si.h:181
@ ShortSmoothingBufferDescriptorTag
Definition: si.h:111
@ PremiereContentTransmissionDescriptorTag
Definition: si.h:188
@ DataStreamAlignmentDescriptorTag
Definition: si.h:57
@ LocalTimeOffsetDescriptorTag
Definition: si.h:102
@ TargetBackgroundGridDescriptorTag
Definition: si.h:58
@ MultilingualServiceNameDescriptorTag
Definition: si.h:107
@ TelephoneDescriptorTag
Definition: si.h:101
@ MHP_ExternalApplicationAuthorisationDescriptorTag
Definition: si.h:175
@ MHP_TransportProtocolDescriptorTag
Definition: si.h:171
@ MHP_DVBHTMLApplicationBoundaryDescriptorTag
Definition: si.h:180
@ VideoStreamDescriptorTag
Definition: si.h:53
@ SubtitlingDescriptorTag
Definition: si.h:103
@ ISO639LanguageDescriptorTag
Definition: si.h:61
@ DefaultAuthorityDescriptorTag
Definition: si.h:130
@ MHP_ApplicationStorageDescriptorTag
Definition: si.h:184
@ AncillaryDataDescriptorTag
Definition: si.h:121
@ MHP_DVBJApplicationLocationDescriptorTag
Definition: si.h:173
@ TimeSliceFecIdentifierDescriptorTag
Definition: si.h:134
@ MultilingualBouquetNameDescriptorTag
Definition: si.h:106
@ SystemClockDescriptorTag
Definition: si.h:62
@ ServiceListDescriptorTag
Definition: si.h:79
@ MHP_IPv4RoutingDescriptorTag
Definition: si.h:176
@ MHP_IPv6RoutingDescriptorTag
Definition: si.h:177
@ ParentalRatingDescriptorTag
Definition: si.h:99
@ DataBroadcastIdDescriptorTag
Definition: si.h:116
@ StuffingDescriptorTag
Definition: si.h:80
@ PDCDescriptorTag
Definition: si.h:119
@ NetworkNameDescriptorTag
Definition: si.h:78
@ AC3DescriptorTag
Definition: si.h:120
@ RegistrationDescriptorTag
Definition: si.h:56
@ CellListDescriptorTag
Definition: si.h:122
@ SatelliteDeliverySystemDescriptorTag
Definition: si.h:81
@ CellFrequencyLinkDescriptorTag
Definition: si.h:123
@ SmoothingBufferDescriptorTag
Definition: si.h:67
@ IBPDescriptorTag
Definition: si.h:69
@ HierarchyDescriptorTag
Definition: si.h:55
@ MHP_DVBJApplicationDescriptorTag
Definition: si.h:172
@ AdaptationFieldDataDescriptorTag
Definition: si.h:126
@ MHP_DVBHTMLApplicationLocationDescriptorTag
Definition: si.h:179
@ MHP_ApplicationDescriptorTag
Definition: si.h:169
@ BouquetNameDescriptorTag
Definition: si.h:85
@ VBIDataDescriptorTag
Definition: si.h:83
@ ContentDescriptorTag
Definition: si.h:98
@ FrequencyListDescriptorTag
Definition: si.h:112
@ ApplicationSignallingDescriptorTag
Definition: si.h:125
@ TerrestrialDeliverySystemDescriptorTag
Definition: si.h:104
@ TimeShiftedEventDescriptorTag
Definition: si.h:93
@ LogicalChannelDescriptorTag
Definition: si.h:142
@ STDDescriptorTag
Definition: si.h:68
@ LinkageDescriptorTag
Definition: si.h:88
@ AACDescriptorTag
Definition: si.h:139
@ AnnouncementSupportDescriptorTag
Definition: si.h:124
@ DSNGDescriptorTag
Definition: si.h:118
@ MHP_ApplicationNameDescriptorTag
Definition: si.h:170
@ ContentIdentifierDescriptorTag
Definition: si.h:133
static char * SystemCharacterTable
Definition: si.c:314
static char * OverrideCharacterTable
Definition: si.c:322
bool SetOverrideCharacterTable(const char *CharacterTable)
Definition: si.c:324
static const char * CharacterTables1[]
Definition: si.c:256
#define MT(s, m, v)
#define NumEntries(Table)
Definition: si.c:312
#define SingleByteLimit
Definition: si.c:291
u_char descriptor_tag
Definition: headers.h:68
#define HILO(x)
Definition: util.h:21