[tivodecode-commits] tivodecode tivo-parse.c, 1.9, 1.10 tivo-parse.h, 1.7, 1.8 tivodecode.c, 1.22,
Status: Alpha
Brought to you by:
jeremyd2019
From: Jeremy D. <jer...@us...> - 2007-04-03 21:11:24
|
Update of /cvsroot/tivodecode/tivodecode In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv7538 Modified Files: tivo-parse.c tivo-parse.h tivodecode.c turing_stream.c turing_stream.h Log Message: refactor tivo file parsing to expose access to the rest of the data, add option to dump out the data chunks in a tivo file to seperate files for analysis (they appear encrypted somehow, but I think the metadata is stored in them somewhere) Index: tivo-parse.h =================================================================== RCS file: /cvsroot/tivodecode/tivodecode/tivo-parse.h,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** tivo-parse.h 31 Dec 2006 21:43:20 -0000 1.7 --- tivo-parse.h 3 Apr 2007 21:11:23 -0000 1.8 *************** *** 34,45 **** unsigned short id; /* Chunk ID */ unsigned short type; /* Subtype */ } tivo_stream_chunk; - - typedef struct { - size_t size; - unsigned char * data; - } blob; - /* genericized read function so that different underlying implementations can * be swapped out for more of a library setup --- 34,40 ---- unsigned short id; /* Chunk ID */ unsigned short type; /* Subtype */ + unsigned char data[1]; /* Variable length data */ } tivo_stream_chunk; /* genericized read function so that different underlying implementations can * be swapped out for more of a library setup *************** *** 47,51 **** typedef int (*read_func_t) (void * mem, int size, void * fh); ! unsigned int parse_tivo(void * file, blob * xml, read_func_t read_handler); #endif --- 42,47 ---- typedef int (*read_func_t) (void * mem, int size, void * fh); ! int read_tivo_header(void * file, tivo_stream_header * head, read_func_t read_handler); ! tivo_stream_chunk * read_tivo_chunk(void * file, read_func_t read_handler); #endif Index: tivodecode.c =================================================================== RCS file: /cvsroot/tivodecode/tivodecode/tivodecode.c,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** tivodecode.c 1 Apr 2007 21:54:08 -0000 1.22 --- tivodecode.c 3 Apr 2007 21:11:23 -0000 1.23 *************** *** 34,37 **** --- 34,38 ---- int o_verbose = 0; int o_no_verify = 0; + int o_dump_chunks = 0; happy_file * hfh=NULL; *************** *** 57,60 **** --- 58,62 ---- {"version", 0, 0, 'V'}, {"no-verify", 0, 0, 'n'}, + {"dump-chunks", 0, 0, 'D'}, {0, 0, 0, 0} }; *************** *** 68,71 **** --- 70,74 ---- ERROUT (" --verbose, -v verbose\n"); ERROUT (" --no-verify, -n do not verify MAK while decoding\n"); + ERROUT (" --dump-chunks,-D dump data chunks from TiVo file to files (development)\n"); ERROUT (" --version, -V print the version information and exit\n"); ERROUT (" --help, -h print this help and exit\n\n"); *************** *** 111,115 **** while (1) { ! int c = getopt_long (argc, argv, "m:o:hnvV", long_options, 0); if (c == -1) --- 114,118 ---- while (1) { ! int c = getopt_long (argc, argv, "m:o:hnDvV", long_options, 0); if (c == -1) *************** *** 135,138 **** --- 138,144 ---- o_no_verify = 1; break; + case 'D': + o_dump_chunks = 1; + break; case '?': do_help(argv[0], 2); *************** *** 238,244 **** PRINT_QUALCOMM_MSG(); ! if ((begin_at = setup_turing_key (&turing, hfh, &hread_wrapper, mak)) < 0) { ! return 8; } --- 244,312 ---- PRINT_QUALCOMM_MSG(); ! if (o_dump_chunks) { ! /* parse the tivo headers manually here, since we care about more ! * than the init_turing_from_file function will get ! */ ! tivo_stream_header head; ! tivo_stream_chunk *chunk; ! int i; ! ! if (read_tivo_header (hfh, &head, &hread_wrapper)) ! return 8; ! ! begin_at = head.mpeg_offset; ! ! for (i = 0; i < head.chunks; i++) ! { ! /* TODO: find a better way to present the chunks */ ! /* maybe a simple tar format writer */ ! char buf[4096]; ! const char * chunk_type_name; ! FILE * chunkfh; ! ! if ((chunk = read_tivo_chunk (hfh, &hread_wrapper)) == NULL) ! return 8; ! ! if (chunk->data_size && chunk->type == TIVO_CHUNK_XML) ! setup_turing_key (&turing, chunk, mak); ! ! switch (chunk->type) ! { ! case TIVO_CHUNK_XML: ! chunk_type_name = "xml"; ! break; ! case TIVO_CHUNK_BLOB: ! chunk_type_name = "blob"; ! break; ! default: ! chunk_type_name = "unknown"; ! break; ! } ! ! sprintf(buf, "%s-%02d-%04x.%s", "chunk", i, chunk->id, chunk_type_name); ! ! chunkfh = fopen(buf, "wb"); ! if (!chunkfh) ! { ! perror("create chunk file"); ! return 8; ! } ! ! if (fwrite (chunk->data, 1, chunk->data_size, chunkfh) != chunk->data_size) ! { ! perror("write chunk"); ! return 8; ! } ! ! fclose(chunkfh); ! ! free(chunk); ! } ! } ! else ! { ! if ((begin_at = init_turing_from_file (&turing, hfh, &hread_wrapper, mak)) < 0) ! return 8; } Index: turing_stream.c =================================================================== RCS file: /cvsroot/tivodecode/tivodecode/turing_stream.c,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** turing_stream.c 1 Apr 2007 04:46:08 -0000 1.13 --- turing_stream.c 3 Apr 2007 21:11:23 -0000 1.14 *************** *** 88,108 **** extern int o_verbose; ! unsigned int setup_turing_key(turing_state * turing, void * tivofile, read_func_t read_handler, char * mak) { ! blob xml; ! SHA1_CTX context; ! unsigned int mpeg_off; ! sha1_init(&context); ! sha1_update(&context, (unsigned char *)mak, strlen(mak)); ! mpeg_off = parse_tivo(tivofile, &xml, read_handler); ! sha1_update(&context, xml.data, xml.size); ! sha1_final(turing->turingkey, &context); ! free (xml.data); ! return mpeg_off; } --- 88,126 ---- extern int o_verbose; ! unsigned int init_turing_from_file(turing_state * turing, void * tivofile, read_func_t read_handler, char * mak) { ! tivo_stream_header head; ! tivo_stream_chunk *xml; ! int i; ! if (read_tivo_header (tivofile, &head, read_handler)) ! return -1; ! for (i = 0; i < head.chunks; i++) ! { ! if ((xml = read_tivo_chunk (tivofile, read_handler)) == NULL) ! return -1; ! if (xml->data_size && xml->type == TIVO_CHUNK_XML) ! { ! setup_turing_key (turing, xml, mak); ! free(xml); ! return head.mpeg_offset; ! } ! else ! free(xml); ! } ! return -1; ! } ! void setup_turing_key(turing_state * turing, tivo_stream_chunk * xml, char * mak) ! { ! SHA1_CTX context; ! ! sha1_init(&context); ! sha1_update(&context, (unsigned char *)mak, strlen(mak)); ! sha1_update(&context, xml->data, xml->data_size); ! sha1_final(turing->turingkey, &context); } Index: tivo-parse.c =================================================================== RCS file: /cvsroot/tivodecode/tivodecode/tivo-parse.c,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** tivo-parse.c 1 Apr 2007 04:46:08 -0000 1.9 --- tivo-parse.c 3 Apr 2007 21:11:23 -0000 1.10 *************** *** 25,87 **** #include "tivo-parse.h" ! #define FILL_NETGNRC(var, buf, offset, size, sz) do { \ ! memcpy (&var, buf + offset, size); \ ! var = ntoh ## sz (var); \ ! } while(0) ! ! #define FILL_NETLONG(var, buf, offset) FILL_NETGNRC(var, buf, offset, sizeof(unsigned int), l) ! #define FILL_NETSHRT(var, buf, offset) FILL_NETGNRC(var, buf, offset, sizeof(unsigned short), s) ! unsigned int parse_tivo(void * file, blob * xml, read_func_t read_handler) { ! char buf[16]; ! tivo_stream_header head; ! tivo_stream_chunk chunk; ! if (read_handler (buf, SIZEOF_STREAM_HEADER, file) != SIZEOF_STREAM_HEADER) { perror ("read head"); return -1; } ! // network byte order conversion ! #if 0 ! // these are unused, don't bother filling them in ! head.dummy_0004=ntohs(head.dummy_0004); ! head.dummy_0006=ntohs(head.dummy_0006); ! head.dummy_0008=ntohs(head.dummy_0008); #endif ! FILL_NETLONG(head.mpeg_offset, buf, 10); ! FILL_NETSHRT(head.chunks, buf, 14); ! if (read_handler (buf, SIZEOF_STREAM_CHUNK, file) != SIZEOF_STREAM_CHUNK) { perror("read chunk head"); ! return -1; } // network byte order conversion ! FILL_NETLONG (chunk.chunk_size, buf, 0); ! FILL_NETLONG (chunk.data_size, buf, 4); ! FILL_NETSHRT (chunk.id, buf, 8); ! FILL_NETSHRT (chunk.type, buf, 10); ! if (chunk.data_size && chunk.type == TIVO_CHUNK_XML) { ! xml->size = chunk.data_size; ! if (!(xml->data = (unsigned char *)malloc(chunk.data_size + 1))) ! { ! perror("malloc"); ! exit(1); ! } ! if (read_handler (xml->data, (int)xml->size, file) != xml->size) ! { ! perror("read chunk data"); ! free(xml->data); ! return -1; ! } } ! return head.mpeg_offset; } --- 25,105 ---- #include "tivo-parse.h" ! #define LOAD_NET_UNALIGNED_HELP(ptr, offset, len) ((unsigned int)ptr[offset] << (((len - 1) << 3) - (offset << 3))) ! #define NETLONG_UNALIGNED(ptr) ( \ ! LOAD_NET_UNALIGNED_HELP(ptr, 0, 4) | \ ! LOAD_NET_UNALIGNED_HELP(ptr, 1, 4) | \ ! LOAD_NET_UNALIGNED_HELP(ptr, 2, 4) | \ ! LOAD_NET_UNALIGNED_HELP(ptr, 3, 4) \ ! ) ! int read_tivo_header(void * file, tivo_stream_header * head, read_func_t read_handler) { ! struct { ! char filetype[4]; ! /* all fields are in network byte order */ ! unsigned short dummy_0004; ! unsigned short dummy_0006; ! unsigned short dummy_0008; ! unsigned char mpeg_offset[4]; /* unsigned int */ ! unsigned short chunks; ! } raw_tivo_header; ! ! if (read_handler (&raw_tivo_header, SIZEOF_STREAM_HEADER, file) != SIZEOF_STREAM_HEADER) { perror ("read head"); return -1; } ! #if 1 ! // these are unused ! memcpy(head->filetype, raw_tivo_header.filetype, 4); ! head->dummy_0004 = ntohs(raw_tivo_header.dummy_0004); ! head->dummy_0006 = ntohs(raw_tivo_header.dummy_0006); ! head->dummy_0008 = ntohs(raw_tivo_header.dummy_0008); #endif ! head->mpeg_offset = NETLONG_UNALIGNED(raw_tivo_header.mpeg_offset); ! head->chunks = ntohs(raw_tivo_header.chunks); ! return 0; ! } ! ! tivo_stream_chunk * read_tivo_chunk(void * file, read_func_t read_handler) ! { ! tivo_stream_chunk * chunk; ! unsigned int chunk_sz; ! tivo_stream_chunk raw_chunk_header; ! ! if (read_handler (&raw_chunk_header, SIZEOF_STREAM_CHUNK, file) != SIZEOF_STREAM_CHUNK) { perror("read chunk head"); ! return NULL; ! } ! ! chunk_sz = ntohl(raw_chunk_header.chunk_size); ! ! /* allocate the memory for the chunk */ ! if (!(chunk = (tivo_stream_chunk *)malloc(chunk_sz))) ! { ! perror("malloc"); ! exit(1); } // network byte order conversion ! chunk->chunk_size = chunk_sz; ! chunk->data_size = ntohl(raw_chunk_header.data_size); ! chunk->id = ntohs(raw_chunk_header.id ); ! chunk->type = ntohs(raw_chunk_header.type ); ! /* read the rest of the chunk */ ! if (read_handler(chunk->data, (int)chunk_sz - SIZEOF_STREAM_CHUNK, file) ! != chunk_sz - SIZEOF_STREAM_CHUNK) { ! perror("read chunk data"); ! free(chunk); ! return NULL; } ! return chunk; } Index: turing_stream.h =================================================================== RCS file: /cvsroot/tivodecode/tivodecode/turing_stream.h,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** turing_stream.h 31 Dec 2006 21:43:21 -0000 1.10 --- turing_stream.h 3 Apr 2007 21:11:23 -0000 1.11 *************** *** 32,36 **** } turing_state; ! unsigned int setup_turing_key(turing_state * turing, void * tivofile, read_func_t read_handler, char * mak); void prepare_frame(turing_state * turing, unsigned char stream_id, int block_id); void decrypt_buffer(turing_state * turing, unsigned char * buffer, size_t buffer_length); --- 32,37 ---- } turing_state; ! unsigned int init_turing_from_file(turing_state * turing, void * tivofile, read_func_t read_handler, char * mak); ! void setup_turing_key(turing_state * turing, tivo_stream_chunk * xml, char * mak); void prepare_frame(turing_state * turing, unsigned char stream_id, int block_id); void decrypt_buffer(turing_state * turing, unsigned char * buffer, size_t buffer_length); |