now working with some basic commands

This commit is contained in:
hummypkg 2011-06-02 23:51:14 +00:00 committed by HummyPkg
parent 36888b42b5
commit 89736f5fab
9 changed files with 499 additions and 180 deletions

View File

@ -12,16 +12,19 @@
struct descriptor *
read_descriptor_header(struct epg *epg)
{
static struct descriptor d;
struct descriptor *d;
d = (struct descriptor *)malloc(sizeof(struct descriptor));
d->loaded = 0;
if (epg->binsize - epg->offset < 2)
return NULL;
memcpy(&d, epg->bin + epg->offset, 2);
memcpy(d, epg->bin + epg->offset, 2);
epg->offset += 2;
return &d;
return d;
}
static char *
@ -44,25 +47,37 @@ string_to_end(struct epg *epg, struct descriptor *d, int sofar,
return str;
}
static char *
read_lstring(struct epg *epg, unsigned int *len)
{
int l = epg->bin[epg->offset++];
char *c;
c = malloc(l + 1);
memcpy(c, epg->bin + epg->offset, l);
c[l] = '\0';
epg->offset += l;
if (len)
*len = l;
return c;
}
void
read_descriptor(struct epg *epg, struct descriptor *d)
{
d->loaded = 1;
switch (d->tag)
{
case DS_SHORT_EVENT:
memcpy(d->content.d77.lang, epg->bin + epg->offset, 3);
epg->offset += 3;
d->content.d77.namelen = epg->bin[epg->offset++];
d->content.d77.name = read_string_len(epg->bin + epg->offset,
d->content.d77.namelen);
epg->offset += d->content.d77.namelen;
d->content.d77.textlen = epg->bin[epg->offset++];
d->content.d77.text = read_string_len(epg->bin + epg->offset,
d->content.d77.textlen);
epg->offset += d->content.d77.textlen;
d->content.d77.name =
read_lstring(epg, &d->content.d77.namelen);
d->content.d77.text =
read_lstring(epg, &d->content.d77.textlen);
break;
case DS_COMPONENT:
@ -74,10 +89,8 @@ read_descriptor(struct epg *epg, struct descriptor *d)
break;
case DS_USER_DEFINED:
d->content.d137.textlen = epg->bin[epg->offset++];
d->content.d137.text = read_string_len(epg->bin + epg->offset,
d->content.d137.textlen);
epg->offset += d->content.d137.textlen;
d->content.d137.text =
read_lstring(epg, &d->content.d137.textlen);
memcpy(d->content.d137.lang, epg->bin + epg->offset, 3);
epg->offset += 3;
@ -87,29 +100,44 @@ read_descriptor(struct epg *epg, struct descriptor *d)
break;
case DS_CONTENT_IDENTIFIER:
memcpy(&d->content.d118, epg->bin + epg->offset, 1);
epg->offset++;
d->content.d118.cridlen = d->content.d118.ref = 0;
switch (d->content.d118.location)
{
unsigned int end = epg->offset + d->len;
d->content.d118.i = 0;
while (epg->offset < end)
{
case 0:
d->content.d118.cridlen = epg->bin[epg->offset++];
d->content.d118.crid = read_string_len(
epg->bin + epg->offset, d->content.d118.cridlen);
epg->offset += d->content.d118.cridlen;
break;
case 1:
d->content.d118.ref =
_swap16((uint16_t)epg->bin[epg->offset]);
/* Not safe to use post increment in macro */
struct crid *crid =
&d->content.d118.crids[d->content.d118.i];
memcpy(crid, epg->bin + epg->offset, 1);
epg->offset++;
break;
default:
printf("Unknown CRID location - %d\n",
d->content.d118.location);
crid->cridlen = crid->ref = 0;
switch (crid->location)
{
case 0:
crid->crid = read_lstring(epg, &crid->cridlen);
break;
case 1:
crid->ref =
_swap16((uint16_t)epg->bin[epg->offset]);
/* Not safe to use post increment in macro */
epg->offset++;
break;
default:
printf("Unknown CRID location - %d\n",
crid->location);
}
if (d->content.d118.i++ >= 3)
{
printf("Too many content IDs.\n");
exit(0);
}
}
break;
}
default:
printf("Default descriptor: %d\n", d->tag);
@ -132,33 +160,45 @@ skip_descriptor(struct epg *epg, struct descriptor *d)
void
free_descriptor(struct descriptor *d)
{
switch (d->tag)
if (d->loaded)
{
case DS_SHORT_EVENT:
if (d->content.d77.name)
free(d->content.d77.name);
if (d->content.d77.text)
free(d->content.d77.text);
break;
case DS_COMPONENT:
if (d->content.d80.text)
free(d->content.d80.text);
break;
case DS_USER_DEFINED:
if (d->content.d137.text)
free(d->content.d137.text);
if (d->content.d137.warning)
free(d->content.d137.warning);
break;
case DS_CONTENT_IDENTIFIER:
if (d->content.d118.crid)
free(d->content.d118.crid);
break;
default:
if (d->content.unknown.text)
free(d->content.unknown.text);
break;
switch (d->tag)
{
case DS_SHORT_EVENT:
if (d->content.d77.name)
free(d->content.d77.name);
if (d->content.d77.text)
free(d->content.d77.text);
break;
case DS_COMPONENT:
if (d->content.d80.text)
free(d->content.d80.text);
break;
case DS_USER_DEFINED:
if (d->content.d137.text)
free(d->content.d137.text);
if (d->content.d137.warning)
free(d->content.d137.warning);
break;
case DS_CONTENT_IDENTIFIER:
{
int i;
for (i = 0; i < d->content.d118.i; i++)
{
struct crid *crid = &d->content.d118.crids[i];
if (crid->cridlen)
free(crid->crid);
}
break;
}
default:
if (d->content.unknown.text)
free(d->content.unknown.text);
break;
}
}
free(d);
}
char *
@ -187,7 +227,7 @@ dump_descriptor(struct descriptor *d, int content)
descriptor_name(d));
DUMPINT(d, len);
if (!content)
if (!content || !d->loaded)
return;
switch (d->tag)
@ -195,10 +235,8 @@ dump_descriptor(struct descriptor *d, int content)
case DS_SHORT_EVENT:
DUMPNSTR(d, content.d77.lang, 3);
DUMPINT(d, content.d77.namelen);
//DUMPNSTR(d, content.d77.name, d->content.d77.namelen);
DUMPHEX(d, content.d77.name, d->content.d77.namelen);
DUMPINT(d, content.d77.textlen);
//DUMPNSTR(d, content.d77.text, d->content.d77.textlen);
DUMPHEX(d, content.d77.text, d->content.d77.textlen);
break;
@ -220,13 +258,23 @@ dump_descriptor(struct descriptor *d, int content)
break;
case DS_CONTENT_IDENTIFIER:
DUMPINT(d, content.d118.location);
DUMPINT(d, content.d118.type);
DUMPINT(d, content.d118.cridlen);
if (d->content.d118.cridlen)
DUMPHEX(d, content.d118.crid, d->content.d118.cridlen);
DUMPINT(d, content.d118.ref);
{
int i;
DUMPINT(d, content.d118.i);
for (i = 0; i < d->content.d118.i; i++)
{
struct crid *crid = &d->content.d118.crids[i];
DUMPINT(crid, location);
DUMPINT(crid, type);
DUMPINT(crid, cridlen);
if (crid->cridlen)
DUMPHEX(crid, crid, crid->cridlen);
DUMPINT(crid, ref);
}
break;
}
default:
if (d->content.unknown.textlen)

View File

@ -7,14 +7,27 @@
#define DS_FTA_CONTENT_MGMT 126
#define DS_USER_DEFINED 137
#define PARSER_SHORT_EVENT 0
#define PARSER_CONTENT_ID 1
#define PARSER_USER_DEFINED 2
#pragma pack(1)
struct crid {
unsigned int location:2;
unsigned int type:6;
unsigned int cridlen;
char *crid;
unsigned int ref:16;
};
struct descriptor {
unsigned int tag:8;
unsigned int len:8;
union {
struct {
char lang[3];
unsigned int namelen:8;
unsigned int textlen:8;
unsigned int namelen;
unsigned int textlen;
char *name;
char *text;
} d77; /* SHORT_EVENT */
@ -28,18 +41,15 @@ struct descriptor {
unsigned int textlen;
} d80; /* COMPONENT */
struct {
unsigned int textlen:8;
unsigned int textlen;
char *text;
char lang[3];
char *warning;
unsigned int warninglen;
} d137; /* USER_DEFINED - content warnings? */
struct {
unsigned int location:2;
unsigned int type:6;
unsigned int cridlen:8;
char *crid;
unsigned int ref:16;
struct crid crids[3];
int i;
} d118; /* CONTENT_IDENTIFIER */
struct {
char *text;
@ -47,5 +57,6 @@ struct descriptor {
} unknown; /* 74, 84, 95, 126, ... */
} content;
int loaded;
};

99
epg.c
View File

@ -71,6 +71,14 @@ read_data(struct epg *epg)
d.start_date = _swap16(d.start_date);
d.u1.comp = _swap16(d.u1.comp);
d.start_hour = bcd(d.start_hour);
d.start_min = bcd(d.start_min);
d.start_sec = bcd(d.start_sec);
d.dur_hour = bcd(d.dur_hour);
d.dur_min = bcd(d.dur_min);
d.dur_sec = bcd(d.dur_sec);
epg->offset += sizeof(d);
return &d;
@ -84,12 +92,11 @@ dump_data(struct data *d)
printf("Data:\n");
DUMPINT(d, event_id);
tm = MJD_TO_UNIX(d->start_date);
printf(" %30s: %#x (%s)\n", "start_date",
d->start_date, ctime_nl(&tm));
tm = mjd(d->start_date, d->start_hour, d->start_min, d->start_sec);
printf(" %30s: %#x %d:%02d:%02d (%s)\n", "start_date",
d->start_date, d->start_hour, d->start_min, d->start_sec,
ctime_nl(&tm));
printf(" %30s: %d:%02d:%02d\n", "start_time",
d->start_hour, d->start_min, d->start_sec);
printf(" %30s: %d:%02d:%02d\n", "duration",
d->dur_hour, d->dur_min, d->dur_sec);
@ -98,3 +105,85 @@ dump_data(struct data *d)
DUMPINT(d, u1.u.descriptors_loop_length);
}
void
parse(char *epgpath,
void (*callback)(struct epg *, struct section *, struct data *,
struct descriptor **, void *), void *val)
{
struct descriptor *dslist[3];
struct epg *epg;
int i;
if (!(epg = open_file(epgpath)))
return;
while (epg->offset < epg->binsize)
{
struct section *s;
uint32_t send;
if (!(s = read_section(epg)))
break;
send = epg->offset - 11 + s->u1.u.length - 4;
while (epg->offset < send)
{
struct data *d;
uint32_t dend;
if (!(d = read_data(epg)))
break;
dslist[0] = dslist[1] = dslist[2] = NULL;
dend = epg->offset + d->u1.u.descriptors_loop_length;
while (epg->offset < dend)
{
struct descriptor *ds;
if (!(ds = read_descriptor_header(epg)))
continue;
switch (ds->tag)
{
case DS_SHORT_EVENT:
read_descriptor(epg, ds);
dslist[PARSER_SHORT_EVENT] = ds;
break;
case DS_CONTENT_IDENTIFIER:
read_descriptor(epg, ds);
dslist[PARSER_CONTENT_ID] = ds;
break;
case DS_USER_DEFINED:
read_descriptor(epg, ds);
dslist[PARSER_USER_DEFINED] = ds;
break;
default:
skip_descriptor(epg, ds);
free_descriptor(ds);
break;
}
}
callback(epg, s, d, dslist, val);
for (i = 0; i < 3; i++)
if (dslist[i])
free_descriptor(dslist[i]);
}
/* Skip CRC */
epg->offset += 4;
/* Skip padding bytes... */
while (epg->bin[epg->offset] == 'U')
epg->offset++;
}
close_file(epg);
}

2
epg.h
View File

@ -1,6 +1,8 @@
#include <sys/param.h>
#define DEFAULT_EPG_FILE "/mnt/hd1/dvbepg/epg.dat"
struct epg {
char fname[MAXPATHLEN + 1];
int fd;

13
lint.h
View File

@ -3,6 +3,8 @@
#include "descriptor.h"
#include "util.h"
#define SYSOPT_PARSABLE 0x1
extern int debug;
extern const char *version;
extern unsigned long sysopts;
@ -12,7 +14,8 @@ inline uint32_t read_uint32(uint8_t *, int);
void hexdump(uint8_t *, uint32_t, uint32_t);
char *hexstr(uint8_t *, uint32_t);
char *ctime_nl(time_t *);
char *read_string_len(uint8_t *, uint32_t);
time_t mjd(uint16_t, int, int, int);
void safeprintf(char *, ...);
struct epg *open_file(char *);
void close_file(struct epg *);
@ -23,9 +26,17 @@ void dump_section(struct section *);
struct data *read_data(struct epg *);
void dump_data(struct data *);
void parse(char *,
void (*)(struct epg *, struct section *, struct data *,
struct descriptor **, void *), void *);
struct descriptor *read_descriptor_header(struct epg *);
void read_descriptor(struct epg *, struct descriptor *);
void skip_descriptor(struct epg *, struct descriptor *);
void dump_descriptor(struct descriptor *, int);
void free_descriptor(struct descriptor *);
#ifdef sun
char *strcasestr (char *, char *);
#endif

233
main.c
View File

@ -25,69 +25,212 @@ syntax()
{
fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011.\n\n", version);
fprintf(stderr,
"Syntax: epg ...\n");
"Syntax: epg [options] <command>...\n");
fprintf(stderr,
" Options:\n"
" -d[level] Set debug level.\n"
" -f<file> Specify alternate EPG data file.\n"
" -h Show help text.\n"
" -p Parsable output.\n"
);
fprintf(stderr, "\n");
fprintf(stderr,
" Commands:\n"
" dump Show a parsed summary of the EPG.\n"
" search <text> Search programme names for text.\n"
" searchall <text> "
"Search programme names/descriptions for text.\n"
);
fprintf(stderr, "\n");
return 0;
}
void
dump(struct epg *epg __attribute__((unused)),
struct section *s, struct data *d, struct descriptor **ds,
void *var __attribute__((unused)))
{
time_t tm;
tm = mjd(d->start_date, d->start_hour, d->start_min, d->start_sec);
printf("----------------------------------------------------------\n");
if (sysopts & SYSOPT_PARSABLE)
{
printf("ServiceID:%d\n", s->service_id);
printf("EventID:%d\n", d->event_id);
printf("Start:%ld\n", tm);
printf("Duration:%d\n",
d->dur_hour * 3600 + d->dur_min * 60 + d->dur_sec);
printf("Encrypted:%d\n", d->u1.u.free_CA_mode);
if (ds[PARSER_SHORT_EVENT])
{
struct descriptor *d77 = ds[PARSER_SHORT_EVENT];
safeprintf("Name:%.*s\n",
d77->content.d77.namelen, d77->content.d77.name);
safeprintf("Text:%.*s\n",
d77->content.d77.textlen, d77->content.d77.text);
}
if (ds[PARSER_USER_DEFINED])
{
struct descriptor *d137 = ds[PARSER_USER_DEFINED];
safeprintf("Warning:%.*s\n",
d137->content.d137.warninglen,
d137->content.d137.warning);
}
if (ds[PARSER_CONTENT_ID])
{
struct descriptor *d118 = ds[PARSER_CONTENT_ID];
int i;
printf("nCRIDs:%d\n", d118->content.d118.i);
for (i = 0; i < d118->content.d118.i; i++)
{
struct crid *crid =
&d118->content.d118.crids[i];
printf("CRID:%d:%.*s\n", crid->type,
crid->cridlen, crid->crid);
}
}
return;
}
printf("%30s: %d\n", "Service ID", s->service_id);
printf("%30s: %d\n", "Event ID", d->event_id);
printf("%30s: %#x %d:%02d:%02d (%s)\n", "start_date",
d->start_date, d->start_hour, d->start_min, d->start_sec,
ctime_nl(&tm));
printf("%30s: %d:%02d:%02d\n", "duration",
d->dur_hour, d->dur_min, d->dur_sec);
printf("%30s: %d\n", "encrypted", d->u1.u.free_CA_mode);
if (ds[PARSER_SHORT_EVENT])
{
struct descriptor *d77 = ds[PARSER_SHORT_EVENT];
safeprintf("%30s: %.*s\n", "Name",
d77->content.d77.namelen, d77->content.d77.name);
safeprintf("%30s: %.*s\n", "Text",
d77->content.d77.textlen, d77->content.d77.text);
}
if (ds[PARSER_USER_DEFINED])
{
struct descriptor *d137 = ds[PARSER_USER_DEFINED];
safeprintf("%30s: %.*s\n", "Warning",
d137->content.d137.warninglen, d137->content.d137.warning);
}
if (ds[PARSER_CONTENT_ID])
{
struct descriptor *d118 = ds[PARSER_CONTENT_ID];
int i;
printf("%30s: %d\n", "CRIDs", d118->content.d118.i);
for (i = 0; i < d118->content.d118.i; i++)
{
struct crid *crid = &d118->content.d118.crids[i];
printf("%30s: %d\n", "CRID Type", crid->type);
printf("%30s: %.*s\n", "CRID",
crid->cridlen, crid->crid);
}
}
}
void
search(struct epg *epg __attribute__((unused)),
struct section *s, struct data *d, struct descriptor **ds,
void *var)
{
if (ds[PARSER_SHORT_EVENT] &&
strcasestr(ds[PARSER_SHORT_EVENT]->content.d77.name, (char *)var))
dump(epg, s, d, ds, NULL);
}
void
searchall(struct epg *epg __attribute__((unused)),
struct section *s, struct data *d, struct descriptor **ds,
void *var)
{
if (ds[PARSER_SHORT_EVENT] && (
strcasestr(ds[PARSER_SHORT_EVENT]->content.d77.name, (char *)var)
||
strcasestr(ds[PARSER_SHORT_EVENT]->content.d77.text, (char *)var)
))
dump(epg, s, d, ds, NULL);
}
int
main(int argc, char **argv)
{
struct section *h;
struct epg *epg;
int i = 0;
char *epgpath = DEFAULT_EPG_FILE;
char *cp;
if (!(epg = open_file("../epg.dat")))
return 0;
while (epg->offset < epg->binsize)
{
uint32_t send;
if (!(h = read_section(epg)))
break;
//dump_section(h);
send = epg->offset - 11 + h->u1.u.length - 4;
while (epg->offset < send)
argc--, argv++;
while (argc > 0 && *argv[0] == '-')
{
for (cp = &argv[0][1]; *cp; cp++)
{
struct data *d;
uint32_t dend;
switch (*cp)
{
case 'd':
if (*++cp == '\0')
debug = 1;
else
debug = atoi(cp);
goto nextopt;
if (!(d = read_data(epg)))
case 'f':
if (*++cp == '\0')
{
fprintf(stderr,
"No argument supplied for -f\n");
exit(1);
}
else
{
while (isspace((int)*cp))
cp++;
epgpath = strdup(cp);
}
goto nextopt;
case 'h':
return syntax();
case 'p':
sysopts |= SYSOPT_PARSABLE;
break;
//dump_data(d);
dend = epg->offset + d->u1.u.descriptors_loop_length;
while (epg->offset < dend)
{
struct descriptor *ds;
ds = read_descriptor_header(epg);
read_descriptor(epg, ds);
/*
if (ds->tag == DS_CONTENT_IDENTIFIER)
dump_descriptor(ds, 1);
*/
free_descriptor(ds);
}
}
/* Skip CRC */
epg->offset += 4;
/* Skip padding bytes... */
while (epg->bin[epg->offset] == 'U')
epg->offset++;
nextopt:
argc--, argv++;
}
close_file(epg);
if (argc < 1)
return syntax();
if (!strcmp(argv[0], "dump"))
parse(epgpath, dump, NULL);
else if (!strcmp(argv[0], "search") && argc > 1)
parse(epgpath, search, (void *)argv[1]);
else if (!strcmp(argv[0], "searchall") && argc > 1)
parse(epgpath, searchall, (void *)argv[1]);
else
syntax();
return 0;
}

42
test
View File

@ -1,42 +0,0 @@
{'CRC_32': 3423408323L,
'current_next_indicator': 1,
'datas': [{'descriptors': [{'descriptor_length': 2,
'descriptor_tag': 84,
'unknown': '\x00\x00'},
{'ISO_639_language_code': 'eng',
'component_tag': 1,
'component_type': 1,
'descriptor_length': 6,
'descriptor_tag': 80,
'reserved_future_use': 15,
'stream_content': 2,
'text': ''},
{'ISO_639_language_code': 'eng',
'descriptor_length': 38,
'descriptor_tag': 77,
'event_name': '\x1f\x01\x05g60\xe3/U\x86$~\xe8\x80',
'event_name_length': 14,
'text': '\x1f\x01\xa9\x89\x1f\xbaS/UO\xaf\xb6\x9dNj\xc8a\xeb\x9d',
'text_length': 19}],
'descriptors_loop_length': 52,
'duration': datetime.timedelta(0, 21600),
'event_id': 795,
'free_CA_mode': 0,
'running_status': 0,
'start_time': datetime.datetime(2011, 6, 1, 0, 0)}],
'last_section_number': 248,
'last_table_id': 97,
'original_network_id': 9018,
'pre_header_1': '(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01',
'pre_header_2': '\x00\x00\x00\x00',
'reserved': 3,
'reserved_future_use': 1,
'section_length': 79,
'section_number': 0,
'section_syntax_indicator': 1,
'segment_last_section_number': 0,
'service_id': 26560,
'table_id': 96,
'total_length': 84,
'transport_stream_id': 24576,
'version_number': 6}

73
util.c
View File

@ -12,6 +12,70 @@
#include "lint.h"
#ifdef sun
char *
strcasestr (char *h, char *n)
{
char *hp, *np = n, *match = 0;
if(!*np) {
return np;
}
for (hp = h; *hp; hp++) {
if (toupper(*hp) == toupper(*np)) {
if (!match) {
match = hp;
}
if(!*++np) {
return match;
}
} else {
if (match) {
match = 0;
np = n;
}
}
}
return NULL;
}
#endif
void
safeprintf(char *fmt, ...)
{
char buf[0x400];
char *p;
va_list argp;
int len;
va_start(argp, fmt);
len = vsprintf(buf, fmt, argp);
va_end(argp);
for (p = buf; p < buf + len; p++)
if (!isprint(*p))
*p = '.';
printf("%.*s\n", len, buf);
}
time_t
mjd(uint16_t day, int h, int m, int s)
{
time_t tm;
struct tm *t;
tm = MJD_TO_UNIX(day);
t = localtime(&tm);
t->tm_hour = h;
t->tm_min = m;
t->tm_sec = s;
return mktime(t);
}
char *
ctime_nl(time_t *tm)
{
@ -23,15 +87,6 @@ ctime_nl(time_t *tm)
return buf;
}
inline char *
read_string_len(uint8_t *src, uint32_t len)
{
char *s = malloc(len + 1);
memcpy(s, src, len);
s[len] = '\0';
return s;
}
inline uint32_t
read_uint32(uint8_t *p, int le)
{

2
util.h
View File

@ -4,6 +4,8 @@
#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8))
#define bcd(v) (((((v) >> 4) & 0xf) * 10) + ((v) & 0xf))
#define DUMPINT(ss,xx) printf(" %30s: %d\n", #xx, ss->xx)
#define DUMPSTR(ss,xx) printf(" %30s: %s\n", #xx, ss->xx)
#define DUMPNSTR(ss,xx,nn) printf(" %30s: %.*s\n", #xx, nn, ss->xx)