Blame | Last modification | View Log | Download
<?php/*Programming infoAll 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 nextpiece of data.numberdecode returns [0] as the integer read, and [1]-1 points to thesymbol that was interprented as the end of the interger (either "e" or":").numberdecode is used for integer decodes both for i11e and 11:hello thereso it is tolerant of the ending symbol.decodelist returns $return[0] as an integer indexed array like you would use in Cfor all the entries. $return[1]-1 is the "e" that ends the list, so [1] is the nextuseful 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 toi12345e 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 errorsbefore they get rejected by the decoder. This is worked around bysuppressing errors.*/// Protect our namespace using a classclass BDecode{function numberdecode($wholefile, $start){$ret[0] = 0;$offset = $start;// 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'){$offset++;$ret[0] = 0;$ret[1] = $offset;return $ret;}return array(false);}while (true){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 overflowsettype($ret[0],"double");//Added 2005.02.21 - VisiGod$ret[0] += ord($wholefile[$offset]) - ord("0");$offset++;}// Tolerate : or e because this is a multiuse functionelse if ($wholefile[$offset] == 'e' || $wholefile[$offset] == ':'){$ret[1] = $offset+1;if ($negative){if ($ret[0] == 0){return array(false);}$ret[0] = - $ret[0];}return $ret;}else{return array(false);}}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"){$offset++;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, $start){$offset = $start+1;$i = 0;if ($wholefile[$start] != 'l'){return array(false);}$ret = array();while (true){if ($wholefile[$offset] == 'e'){break;}$value = $this->decodeEntry($wholefile, $offset);if ($value[0] === false){return array(false);}$ret[$i] = $value[0];$offset = $value[1];$i ++;}// The empy list is an empty array. Seems fine.$final[0] = $ret;$final[1] = $offset+1;return $final;}// Tries to construct an arrayfunction decodeDict($wholefile, $start=0){$offset = $start;if ($wholefile[$offset] == 'l'){return $this->decodeList($wholefile, $start);}if ($wholefile[$offset] != 'd'){return false;}$ret = array();$offset++;while (true){if ($wholefile[$offset] == 'e'){$offset++;break;}$left = $this->decodeEntry($wholefile, $offset);if (!$left[0]){return false;}$offset = $left[1];if ($wholefile[$offset] == 'd'){// Recurse$value = $this->decodedict($wholefile, $offset);if (!$value[0]){return false;}$ret[addslashes($left[0])] = $value[0];$offset= $value[1];continue;}else 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];}else{$value = $this->decodeEntry($wholefile, $offset);if ($value[0] === false){return false;}$ret[addslashes($left[0])] = $value[0];$offset = $value[1];}}if (empty($ret)){$final[0] = true;}else{$final[0] = $ret;}$final[1] = $offset;return $final;}} // 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];}?>