1/* MiniDLNA media server 2 * Copyright (C) 2009 Justin Maggard 3 * 4 * This file is part of MiniDLNA. 5 * 6 * MiniDLNA is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * MiniDLNA is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>. 17 */ 18#include "config.h" 19#ifdef TIVO_SUPPORT 20#include <stdlib.h> 21#include <stdint.h> 22#include <string.h> 23#include <ctype.h> 24#include <unistd.h> 25#include <fcntl.h> 26#include <sys/types.h> 27#include <sqlite3.h> 28#include "tivo_utils.h" 29 30/* This function based on byRequest */ 31char * 32decodeString(char *string, int inplace) 33{ 34 if( !string ) 35 return NULL; 36 int alloc = (int)strlen(string)+1; 37 char *ns = NULL; 38 unsigned char in; 39 int strindex=0; 40 long hex; 41 42 if( !inplace ) 43 { 44 if( !(ns = malloc(alloc)) ) 45 return NULL; 46 } 47 48 while(--alloc > 0) 49 { 50 in = *string; 51 if((in == '%') && isxdigit(string[1]) && isxdigit(string[2])) 52 { 53 /* this is two hexadecimal digits following a '%' */ 54 char hexstr[3]; 55 char *ptr; 56 hexstr[0] = string[1]; 57 hexstr[1] = string[2]; 58 hexstr[2] = 0; 59 60 hex = strtol(hexstr, &ptr, 16); 61 62 in = (unsigned char)hex; /* this long is never bigger than 255 anyway */ 63 if( inplace ) 64 { 65 *string = in; 66 memmove(string+1, string+3, alloc-2); 67 } 68 else 69 { 70 string+=2; 71 } 72 alloc-=2; 73 } 74 if( !inplace ) 75 ns[strindex++] = in; 76 string++; 77 } 78 if( inplace ) 79 { 80 free(ns); 81 return string; 82 } 83 else 84 { 85 ns[strindex] = '\0'; /* terminate it */ 86 return ns; 87 } 88} 89 90/* These next functions implement a repeatable random function with a user-provided seed */ 91static int 92seedRandomByte(uint32_t seed) 93{ 94 unsigned char t; 95 96 if( !sqlite3Prng.isInit ) 97 { 98 int i; 99 char k[256]; 100 sqlite3Prng.j = 0; 101 sqlite3Prng.i = 0; 102 memset(&k, '\0', sizeof(k)); 103 memcpy(&k, &seed, 4); 104 for(i=0; i<256; i++) 105 sqlite3Prng.s[i] = i; 106 for(i=0; i<256; i++) 107 { 108 sqlite3Prng.j += sqlite3Prng.s[i] + k[i]; 109 t = sqlite3Prng.s[sqlite3Prng.j]; 110 sqlite3Prng.s[sqlite3Prng.j] = sqlite3Prng.s[i]; 111 sqlite3Prng.s[i] = t; 112 } 113 sqlite3Prng.isInit = 1; 114 } 115 /* Generate and return single random byte */ 116 sqlite3Prng.i++; 117 t = sqlite3Prng.s[sqlite3Prng.i]; 118 sqlite3Prng.j += t; 119 sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j]; 120 sqlite3Prng.s[sqlite3Prng.j] = t; 121 t += sqlite3Prng.s[sqlite3Prng.i]; 122 123 return sqlite3Prng.s[t]; 124} 125 126static void 127seedRandomness(int n, void *pbuf, uint32_t seed) 128{ 129 unsigned char *zbuf = pbuf; 130 131 while( n-- ) 132 *(zbuf++) = seedRandomByte(seed); 133} 134 135void 136TiVoRandomSeedFunc(sqlite3_context *context, int argc, sqlite3_value **argv) 137{ 138 int64_t r, seed; 139 140 if( argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_INTEGER ) 141 return; 142 seed = sqlite3_value_int64(argv[0]); 143 seedRandomness(sizeof(r), &r, seed); 144 sqlite3_result_int64(context, r); 145} 146 147int 148is_tivo_file(const char *path) 149{ 150 unsigned char buf[5]; 151 unsigned char hdr[5] = { 'T','i','V','o','\0' }; 152 int fd; 153 154 /* read file header */ 155 fd = open(path, O_RDONLY); 156 if( fd < 0 ) 157 return 0; 158 if( read(fd, buf, 5) < 5 ) 159 buf[0] = 'X'; 160 close(fd); 161 162 return !memcmp(buf, hdr, 5); 163} 164 165#endif 166