aboutsummaryrefslogtreecommitdiff
path: root/Html/includes/BDecode.php
diff options
context:
space:
mode:
Diffstat (limited to 'Html/includes/BDecode.php')
-rw-r--r--Html/includes/BDecode.php172
1 files changed, 172 insertions, 0 deletions
diff --git a/Html/includes/BDecode.php b/Html/includes/BDecode.php
new file mode 100644
index 0000000..fbf12bc
--- /dev/null
+++ b/Html/includes/BDecode.php
@@ -0,0 +1,172 @@
+<?php
+/*
+ Programming info
+
+All functions output a small array, which we'll call $return for now.
+
+$return[0] is the data expected of the function
+$return[1] is the offset over the whole bencoded data of the next
+ piece of data.
+
+numberdecode returns [0] as the integer read, and [1]-1 points to the
+symbol that was interprented as the end of the interger (either "e" or
+":").
+numberdecode is used for integer decodes both for i11e and 11:hello there
+so it is tolerant of the ending symbol.
+
+decodelist returns $return[0] as an integer indexed array like you would use in C
+for all the entries. $return[1]-1 is the "e" that ends the list, so [1] is the next
+useful byte.
+
+decodeDict returns $return[0] as an array of text-indexed entries. For example,
+$return[0]["announce"] = "http://www.whatever.com:6969/announce";
+$return[1]-1 again points to the "e" that ends the dictionary.
+
+decodeEntry returns [0] as an integer in the case $offset points to
+i12345e or a string if $offset points to 11:hello there style strings.
+It also calls decodeDict or decodeList if it encounters a d or an l.
+
+Known bugs:
+- The program doesn't pay attention to the string it's working on.
+ A zero-sized or truncated data block will cause string offset errors
+ before they get rejected by the decoder. This is worked around by
+ suppressing errors.
+*/
+
+// Protect our namespace using a class
+class BDecode {
+ function numberdecode($wholefile, $offset) {
+ // Funky handling of negative numbers and zero
+ $negative = false;
+ if ($wholefile[$offset] == '-') {
+ $negative = true;
+ $offset++;
+ }
+ if ($wholefile[$offset] == '0') {
+ $offset++;
+ if ($negative)
+ return array(false);
+ if ($wholefile[$offset] == ':' || $wholefile[$offset] == 'e'){
+
+ return array(0, ++$offset);
+ }
+
+ return array(false);
+ }
+ $ret[0] = 0;
+ for(;;) {
+ if ($wholefile[$offset] >= '0' && $wholefile[$offset] <= '9') {
+ $ret[0] *= 10;
+ //Added 2005.02.21 - VisiGod
+ //Changing the type of variable from integer to double to prevent a numeric overflow
+ settype($ret[0],'double');
+ //Added 2005.02.21 - VisiGod
+ $ret[0] += ord($wholefile[$offset]) - ord('0');
+ $offset++;
+ } else if ($wholefile[$offset] == 'e' || $wholefile[$offset] == ':') {
+ // Tolerate : or e because this is a multiuse function
+ $ret[1] = $offset+1;
+ if ($negative) {
+ if ($ret[0] == 0)
+ return array(false);
+ $ret[0] = - $ret[0];
+ }
+ return $ret;
+ } else return array(false);
+ }
+ }
+
+ function decodeEntry($wholefile, $offset=0) {
+ if ($wholefile[$offset] == 'd')
+ return $this->decodeDict($wholefile, $offset);
+ if ($wholefile[$offset] == 'l')
+ return $this->decodelist($wholefile, $offset);
+ if ($wholefile[$offset] == 'i')
+ return $this->numberdecode($wholefile, ++$offset);
+ // String value: decode number, then grab substring
+
+ $info = $this->numberdecode($wholefile, $offset);
+
+ if ($info[0] === false)
+ return array(false);
+ $ret[0] = substr($wholefile, $info[1], $info[0]);
+ $ret[1] = $info[1]+strlen($ret[0]);
+
+
+ return $ret;
+ }
+
+ function decodeList($wholefile, $offset) {
+ if ($wholefile[$offset] != 'l')
+ return array(false);
+ $offset++;
+ $ret = array();
+ for ($i=0;;$i++) {
+ if ($wholefile[$offset] == 'e')
+ break;
+ $value = $this->decodeEntry($wholefile, $offset);
+ if ($value[0] === false)
+ return array(false);
+ $ret[$i] = $value[0];
+ $offset = $value[1];
+ }
+ // The empty list is an empty array. Seems fine.
+ return array(0=>$ret, 1=>++$offset);
+ }
+
+ // Tries to construct an array
+ function decodeDict($wholefile, $offset=0) {
+ if ($wholefile[$offset] == 'l')
+ return $this->decodeList($wholefile, $offset);
+ if ($wholefile[$offset] != 'd')
+ return false;
+ $ret=array();
+ $offset++;
+ for (;;) {
+ if ($wholefile[$offset] == 'e') {
+ $offset++;
+ break;
+ }
+ $left = $this->decodeEntry($wholefile, $offset);
+ if ($left[0]===false) {
+ die("stop...".$left[1]);
+ return false;
+ }
+
+ $offset = $left[1];
+ if ($wholefile[$offset] == 'd') {
+ // Recurse
+ $value = $this->decodedict($wholefile, $offset);
+ if ($value[0]) {
+ $ret[addslashes($left[0])] = $value[0];
+ $offset= $value[1];
+ }
+ continue;
+ }
+ if ($wholefile[$offset] == 'l') {
+ $value = $this->decodeList($wholefile, $offset);
+ if (!$value[0] && is_bool($value[0]))
+ return false;
+ $ret[addslashes($left[0])] = $value[0];
+ $offset = $value[1];
+ continue;
+ }
+ $value = $this->decodeEntry($wholefile, $offset);
+ if ($value[0] === false)
+ return false;
+ $ret[addslashes($left[0])] = $value[0];
+ $offset = $value[1];
+
+ }
+
+ return array(0=>(empty($ret)?true:$ret), 1=>$offset);
+ }
+} // End of class declaration.
+
+// Use this function. eg: BDecode("d8:announce44:http://www. ... e");
+function BDecode($wholefile) {
+ $decoder = new BDecode;
+ $return = $decoder->decodeEntry($wholefile);
+ return $return[0];
+}
+?> \ No newline at end of file