So there I was working on validating the data coming into the node and I started to look into the bencoding/decoding functions that were in the 4.7 module. I started to messing around with the functions that were implemented. I analyzed the data from bdec() which returns something similar to:
[announce] => Array (
[type] => string
[value] => http://torrent.linux.duke.edu:6969/announce
[strlen] => 46
[string] => 43:http://torrent.linux.duke.edu:6969/announce )
This is fine, but when the arrays start getting nested with varying keys the entire output of the function becomes a tangled mess. So for my first task I set out to take all of this data and put it in an easy to access structure modeled after a torrent file:
$files = array("The", "files", "go", "here"); // I know that this is not correct :)
$pieces = "string containing piece data"; // This is a LOT of data
$bparsed = bdec();
$parsed = array(
'announce' => $bparsed['value']['announce']['value'],
'creation date' => $bparsed['value']['creation date']['value'],
'info' => array(
'files' => $files,
'name' => $bparsed['value']['info']['value']['name']['value'],
'piece length' => $bparsed['value']['info']['value']['piece length']['value'],
'pieces' => $pieces)
);
Now that I have this data in a nice format I want see what the benc() function will do to it. As a side not I tried encoding the result of bdec(), it wasn't pretty :). I ran:
benc($parsed);
I then compared the original torrent file with the new generated output. I noticed errors in the files section, instead of using lists the function was creating dictionaries with the integer key as the key for the dictionary. This would work, I want the output to match the original torrent. So I set about modifying the code.
Before:
$out = 'd';
ksort($struct);
foreach($struct as $key => $value) {
$out .= benc($key);
$out .= benc($value);
}
$out .= 'e';
return $out;
After:
$numeric = true;
foreach(array_keys($struct) as $key_value){
if(!is_numeric($key_value))
$numeric = false;
}
if(!$numeric){
$out = 'd';
ksort($struct);
foreach($struct as $key => $value) {
$out .= benc($key);
$out .= benc($value);
}
$out .= 'e';
} else {
$out = 'l';
ksort($struct);
foreach($struct as $key => $value) {
//$out .= benc($key);
$out .= benc($value);
}
$out .= 'e';
}
return $out;
Now should an array be sent to the function where the keys are numbers the array will be converted into a list. With this change the encoding function returns the exact values that the original torrent. I noticed as I was cleaning up my work that I was not taking into account a single file torrent. This should be easy to implement / check for as a single file torrent has a "length" attribute within the info section instead of a files section.
Overall using these functions has cleaned up my code for instance when generating the info hash for the torrent before I was using:
preg_match('/4:info/', $values['metadata'], $matches, PREG_OFFSET_CAPTURE);
$offset = $matches[0][1] + 6;
$info = substr($values['metadata'], $offset, (strlen($values['metadata'])-$offset-1));
$values['info_hash'] = sha1($info);
Now I have this:
strtoupper(sha1(benc($parsed['info'])))
I prefer the second to the first :). With all of these excellent functions in place I think I can finish the torrent node type this week. Moving on to the tracker afterwards. Any questions or comments send me a message I am always looking for input. Until next time,
~Chris