Browse code

Import from the old rivettracker git repository at sourceforge (amisaph/amisapphire branch)

Clarissa Walker (ami-sapphire) authored on 2014/01/24 14:02:23
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,217 @@
1
+<?php
2
+/*
3
+
4
+	Programming info
5
+
6
+All functions output a small array, which we'll call $return for now.
7
+
8
+$return[0] is the data expected of the function
9
+$return[1] is the offset over the whole bencoded data of the next
10
+           piece of data.
11
+
12
+numberdecode returns [0] as the integer read, and [1]-1 points to the
13
+symbol that was interprented as the end of the interger (either "e" or
14
+":"). 
15
+numberdecode is used for integer decodes both for i11e and 11:hello there
16
+so it is tolerant of the ending symbol.
17
+
18
+decodelist returns $return[0] as an integer indexed array like you would use in C
19
+for all the entries. $return[1]-1 is the "e" that ends the list, so [1] is the next
20
+useful byte.
21
+
22
+decodeDict returns $return[0] as an array of text-indexed entries. For example,
23
+$return[0]["announce"] = "http://www.whatever.com:6969/announce";
24
+$return[1]-1 again points to the "e" that ends the dictionary.
25
+
26
+decodeEntry returns [0] as an integer in the case $offset points to
27
+i12345e or a string if $offset points to 11:hello there style strings.
28
+It also calls decodeDict or decodeList if it encounters a d or an l.
29
+
30
+
31
+Known bugs:
32
+- The program doesn't pay attention to the string it's working on.
33
+  A zero-sized or truncated data block will cause string offset errors
34
+  before they get rejected by the decoder. This is worked around by
35
+  suppressing errors.
36
+
37
+*/
38
+
39
+// Protect our namespace using a class
40
+class BDecode
41
+{
42
+
43
+function numberdecode($wholefile, $start)
44
+{
45
+	$ret[0] = 0;
46
+	$offset = $start;
47
+
48
+	// Funky handling of negative numbers and zero
49
+	$negative = false;
50
+	if ($wholefile[$offset] == '-')
51
+	{
52
+		$negative = true;
53
+		$offset++;
54
+	}
55
+	if ($wholefile[$offset] == '0')
56
+	{
57
+		$offset++;
58
+		if ($negative)
59
+			return array(false);
60
+		if ($wholefile[$offset] == ':' || $wholefile[$offset] == 'e')
61
+		{
62
+			$offset++;
63
+			$ret[0] = 0;
64
+			$ret[1] = $offset;
65
+			return $ret;
66
+		}
67
+		return array(false);
68
+	}
69
+	while (true)
70
+	{
71
+
72
+		if ($wholefile[$offset] >= '0' && $wholefile[$offset] <= '9')
73
+		{
74
+			
75
+			$ret[0] *= 10;
76
+			$ret[0] += ord($wholefile[$offset]) - ord("0");
77
+			$offset++;
78
+		}
79
+		// Tolerate : or e because this is a multiuse function
80
+		else if ($wholefile[$offset] == 'e' || $wholefile[$offset] == ':')
81
+		{
82
+			$ret[1] = $offset+1;
83
+			if ($negative)
84
+			{
85
+				if ($ret[0] == 0)
86
+					return array(false);
87
+				$ret[0] = - $ret[0];
88
+			}
89
+			return $ret;
90
+		}
91
+		else
92
+			return array(false);
93
+	}
94
+
95
+}
96
+
97
+function decodeEntry($wholefile, $offset=0)
98
+{
99
+	if ($wholefile[$offset] == 'd')
100
+		return $this->decodeDict($wholefile, $offset);
101
+	if ($wholefile[$offset] == 'l')
102
+		return $this->decodelist($wholefile, $offset);
103
+	if ($wholefile[$offset] == "i")
104
+	{
105
+		$offset++;
106
+		return $this->numberdecode($wholefile, $offset);
107
+	}
108
+	// String value: decode number, then grab substring
109
+	$info = $this->numberdecode($wholefile, $offset);
110
+	if ($info[0] === false)
111
+		return array(false);
112
+	$ret[0] = substr($wholefile, $info[1], $info[0]);
113
+	$ret[1] = $info[1]+strlen($ret[0]);
114
+	return $ret;
115
+}
116
+
117
+function decodeList($wholefile, $start)
118
+{
119
+	$offset = $start+1;
120
+	$i = 0;
121
+	if ($wholefile[$start] != 'l')
122
+		return array(false);
123
+	$ret = array();
124
+	while (true)
125
+	{
126
+		if ($wholefile[$offset] == 'e')
127
+			break;
128
+		$value = $this->decodeEntry($wholefile, $offset);
129
+		if ($value[0] === false)
130
+			return array(false);
131
+		$ret[$i] = $value[0];
132
+		$offset = $value[1];
133
+		$i ++;
134
+	}
135
+
136
+	// The empy list is an empty array. Seems fine.
137
+	$final[0] = $ret;
138
+	$final[1] = $offset+1;
139
+	return $final;
140
+
141
+
142
+
143
+}
144
+
145
+// Tries to construct an array
146
+function decodeDict($wholefile, $start=0)
147
+{
148
+	$offset = $start;
149
+	if ($wholefile[$offset] == 'l')
150
+		return $this->decodeList($wholefile, $start);
151
+	if ($wholefile[$offset] != 'd')
152
+		return false;
153
+	$ret = array();
154
+	$offset++;
155
+	while (true)
156
+	{	
157
+		if ($wholefile[$offset] == 'e')
158
+		{
159
+			$offset++;
160
+			break;
161
+		}
162
+		$left = $this->decodeEntry($wholefile, $offset);
163
+		if (!$left[0])
164
+			return false;
165
+		$offset = $left[1];
166
+		if ($wholefile[$offset] == 'd')
167
+		{
168
+			// Recurse
169
+			$value = $this->decodedict($wholefile, $offset);
170
+			if (!$value[0])
171
+				return false;
172
+			$ret[addslashes($left[0])] = $value[0];
173
+			$offset= $value[1];
174
+			continue;
175
+		}
176
+		else if ($wholefile[$offset] == 'l')
177
+		{
178
+			$value = $this->decodeList($wholefile, $offset);
179
+			if (!$value[0] && is_bool($value[0]))
180
+				return false;
181
+			$ret[addslashes($left[0])] = $value[0];
182
+			$offset = $value[1];
183
+		}
184
+		else
185
+		{
186
+ 			$value = $this->decodeEntry($wholefile, $offset);
187
+			if ($value[0] === false)
188
+				return false;
189
+			$ret[addslashes($left[0])] = $value[0];
190
+			$offset = $value[1];
191
+		}
192
+	}
193
+	if (empty($ret))
194
+		$final[0] = true;
195
+	else
196
+		$final[0] = $ret;
197
+	$final[1] = $offset;
198
+   	return $final;
199
+
200
+
201
+}
202
+
203
+
204
+} // End of class declaration.
205
+
206
+
207
+
208
+// Use this function. eg:  BDecode("d8:announce44:http://www. ... e");
209
+function BDecode($wholefile)
210
+{
211
+	$decoder = new BDecode;
212
+	$return = $decoder->decodeEntry($wholefile);
213
+	return $return[0];
214
+}
215
+
216
+
217
+?>
0 218
\ No newline at end of file