$value) { $return .= self::encode_string($key); $return .= self::encode($value); } $return .= 'e'; return $return; } /** * Pass in a bencoded string and get back an int, string, or array * depending on the bencoded data. * * @param $data string * @return mixed */ public static function decode($data) { // every time something external calls decode we will reset the pointer // it will be left alone for internal recursive calls return self::_decode($data, TRUE); } /** * Does the actual decoding. This is private so that the caller cannot * request the pointer to be reset. * * @param $data string * @param $reset_pointer boolean * @return mixed */ private static function _decode($data, $reset_pointer = FALSE) { static $pointer = 0; if ($reset_pointer) $pointer = 0; // decoding a string if (is_numeric($data[$pointer])) { $strlength = ''; while (is_numeric($data[$pointer])) { $strlength .= $data[$pointer]; $pointer++; } $pointer++; $strlength = (int)$strlength; $decoded = substr($data, $pointer, $strlength); $pointer += $strlength; } else { switch ($data[$pointer]) { // decoding an integer case 'i': $number = ''; $pointer++; // advance past the 'i' while (is_numeric($data[$pointer])) { $number .= $data[$pointer]; $pointer++; } $pointer++; // advance past the ending 'e' $decoded = (int)$number; break; // decoding a list case 'l': $decoded = array(); $pointer++; // advance past the 'l' while (isset($data[$pointer]) && $data[$pointer] != 'e') { $decoded[] = self::_decode($data); } $pointer++; // advance past the ending 'e' break; // decoding a dictionary case 'd': $decoded = array(); $pointer++; // advance past the 'd' while (isset($data[$pointer]) && $data[$pointer] != 'e') { $decoded[self::_decode($data)] = self::_decode($data); } $pointer++; // advance past ending 'e' break; // encountered invalid bencoding default: throw new Exception('invalid data: [' . $pointer . '] = ' . $data[$pointer]); } } return $decoded; } } // // TESTS: // // ENCODING // int $data = 3; var_dump(bencoder::encode($data)); // list $data = array(45,754,5434); var_dump(bencoder::encode($data)); // dictionary $data = array ( 'cow' => 'moo', 'spam' => 'eggs' ); var_dump(bencoder::encode($data)); // list nested in dictionary $data = array ( 'spam' => array ('a','b') ); var_dump(bencoder::encode($data)); // nested lists $data = array ( array(1,2,3), array(3,2,1) ); var_dump(bencoder::encode($data)); // DECODING: // string $data = '4:spam'; var_dump(bencoder::decode($data)); // int $data = 'i5435e'; var_dump(bencoder::decode($data)); // list $data = 'li45ei754ei5434ee'; var_dump(bencoder::decode($data)); // nested lists $data = 'lli1ei2ei3eeli3ei2ei1eee'; var_dump(bencoder::decode($data)); // list nested in dictionary $data = 'd4:spaml1:a1:bee'; var_dump(bencoder::decode($data));