Skip to content

Instantly share code, notes, and snippets.

@sj26
Created February 16, 2010 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sj26/305392 to your computer and use it in GitHub Desktop.
Save sj26/305392 to your computer and use it in GitHub Desktop.
<?php
/**
* Really simple, concise and fairly efficient bencode/bdecode functions
* for manipulating BitTorrent metadata within PHP.
* Lookout for a C PHP extension coming to a server near you!
* by Samuel Cochran <sj26@sj26.com>
*/
function bdecode($stream) {
if (feof($stream)) {
throw new Exception('Unexpected end of stream while reading.');
}
$c = fgetc($stream);
if ($c == 'd') {
$v = array();
while (($k = bdecode($stream)) !== NULL) {
if (!is_string($k))
throw new Exception('Dictionary keys must be strings.');
$v[$k] = bdecode($stream);
}
} else if ($c == 'l') {
$v = array();
while (($e = bdecode($stream)) !== NULL) {
$v[] = $e;
}
} else if ($c == 'i') {
$v = 0;
while (($c = fgetc($stream)) !== FALSE) {
if (is_numeric($c)) {
$v = $v * 10 + intval($c);
} else if ($c == 'e') {
break;
} else {
throw new Exception('Unexpected character while reading integer: '.$c);
}
}
if (feof($stream)) {
throw new Exception('Unexpected end of stream while reading string length.');
}
} else if ($c == 'e') {
$v = NULL;
} else if (is_numeric($c)) {
$l = intval($c);
while (($c = fgetc($stream)) !== FALSE) {
if (is_numeric($c)) {
$l = $l * 10 + intval($c);
} else if ($c == ':') {
break;
} else {
throw new Exception('Unexpected character while reading string length: '.$c);
}
}
if (feof($stream)) {
throw new Exception('Unexpected end of stream while reading string length.');
}
$v = '';
while (strlen($v) < $l) {
if (($s = fread($stream, $l - strlen($v))) === FALSE) {
throw new Exception('Unexpected end of stream while reading string.');
} else {
$v .= $s;
}
}
}
return $v;
}
function bencode($value) {
if (is_null($value)) {
$s = '0:';
} else if (is_int($value) || is_double($value)) {
$s = 'i' . (int)($value) . 'e';
} else if (is_string($value)) {
$s = strlen($value).':'.$value;
} else if (is_array($value)) {
$l = true;
foreach(array_keys($value) as $key) {
if (!is_int($key)) {
$l = false;
break;
}
}
if ($l) {
$s = 'l';
ksort($value, SORT_NUMERIC);
foreach($value as $v) {
$s .= bencode($v);
}
$s .= 'e';
} else {
$s = 'd';
ksort($value, SORT_STRING);
foreach($value as $k => $v) {
$s .= bencode(strval($k));
$s .= bencode($v);
}
$s .= 'e';
}
} else {
throw new Exception('Cannot encode value, unsupported type: '.$value);
}
return $s;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment