1/*  MiniDLNA media server
2 *  Copyright (C) 2009  Justin Maggard
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 *  This program is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 *  GNU General Public License for more details.
13 *
14 *  You should have received a copy of the GNU General Public License
15 *  along with this program; if not, write to the Free Software
16 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18#include "config.h"
19#ifdef TIVO_SUPPORT
20#include <stdlib.h>
21#include <string.h>
22#include <ctype.h>
23#include <linux/types.h> // Defines __u32
24#include <sqlite3.h>
25#include "tivo_utils.h"
26
27/* This function based on byRequest */
28char *
29decodeString(char * string, int inplace)
30{
31	if( !string )
32		return NULL;
33	int alloc = (int)strlen(string)+1;
34	char * ns = NULL;
35	unsigned char in;
36	int strindex=0;
37	long hex;
38
39	if( !inplace )
40	{
41		if( !(ns = malloc(alloc)) )
42			return NULL;
43	}
44
45	while(--alloc > 0)
46	{
47		in = *string;
48		if((in == '%') && isxdigit(string[1]) && isxdigit(string[2]))
49		{
50			/* this is two hexadecimal digits following a '%' */
51			char hexstr[3];
52			char *ptr;
53			hexstr[0] = string[1];
54			hexstr[1] = string[2];
55			hexstr[2] = 0;
56
57			hex = strtol(hexstr, &ptr, 16);
58
59			in = (unsigned char)hex; /* this long is never bigger than 255 anyway */
60			if( inplace )
61			{
62				*string = in;
63				memmove(string+1, string+3, alloc-2);
64			}
65			else
66			{
67				string+=2;
68			}
69			alloc-=2;
70		}
71		if( !inplace )
72			ns[strindex++] = in;
73		string++;
74	}
75	if( inplace )
76	{
77		return string;
78	}
79	else
80	{
81		ns[strindex] = '\0'; /* terminate it */
82		return ns;
83	}
84}
85
86/* These next functions implement a repeatable random function with a user-provided seed */
87static int
88seedRandomByte(__u32 seed) {
89  unsigned char t;
90  if( !sqlite3Prng.isInit )
91  {
92    int i;
93    char k[256];
94    sqlite3Prng.j = 0;
95    sqlite3Prng.i = 0;
96    memset(&k, 0, 256);
97    memcpy(&k, &seed, 4);
98    for(i=0; i<256; i++){
99      sqlite3Prng.s[i] = i;
100    }
101    for(i=0; i<256; i++){
102      sqlite3Prng.j += sqlite3Prng.s[i] + k[i];
103      t = sqlite3Prng.s[sqlite3Prng.j];
104      sqlite3Prng.s[sqlite3Prng.j] = sqlite3Prng.s[i];
105      sqlite3Prng.s[i] = t;
106    }
107    sqlite3Prng.isInit = 1;
108  }
109  /* Generate and return single random byte */
110  sqlite3Prng.i++;
111  t = sqlite3Prng.s[sqlite3Prng.i];
112  sqlite3Prng.j += t;
113  sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j];
114  sqlite3Prng.s[sqlite3Prng.j] = t;
115  t += sqlite3Prng.s[sqlite3Prng.i];
116
117  return sqlite3Prng.s[t];
118}
119
120void
121seedRandomness(int N, void *pBuf, __u32 seed){
122  unsigned char *zBuf = pBuf;
123
124  while( N-- ){
125    *(zBuf++) = seedRandomByte(seed);
126  }
127}
128
129void
130TiVoRandomSeedFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
131{
132  sqlite_int64 r, seed;
133  if( argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_INTEGER )
134	return;
135  seed = sqlite3_value_int64(argv[0]);
136  seedRandomness(sizeof(r), &r, seed);
137  sqlite3_result_int64(context, r);
138}
139#endif
140